Android Development: Switching between Views without losing onClickListeners - android

On my application I'm developing, the main.xml layout (the default layout of my app) has a few buttons that have been assigned onClickListeners (not the implementation way).
One of those buttons I want to have the ability to take you to another view. On the other view (preview.xml), there's another button that takes you back to the main.xml view.
I've used setContentView in the onClickListeners of those buttons and this works fine so far, but after you click the button that takes you back to main.xml, the buttons on main.xml have lost their onClick functionalities.
How can I get this to work right? I presume using setContentView isn't the right way to do this.

Your best bet, at Konstantin says above is to use Activities, as you will come across these a lot whilst developing for android. you can read about them here Activities. I assume you want to pass something onto the preview.xml page? If so, I'd recommend either putting it as an extra in the Intent used to start the activity (see the link) or creating a static reference in the activity (which you set before you launch it).

I'd say use two different activities and switch between them. Another option can be ViewSwitcher.

Related

I can't get my button to work on my second layout (Android)

I've spent 8 years programming and for 8 years I've been pretty happy, but after using Android Studio for two weeks I already want to
So here's the deal. I made 2 layouts. One is the default, named activity_main.xml, the other is named graph_layout.xml. They are both ConstraintLayouts (but the same issue occurred when I tried making graph_layout a LinearLayout or RelativeLayout, so we can rule that out as a factor).
In activity_main, there's a button with the ID, graph_button_1. When I click it, it prints to the console "AAAAAAAAAAAAAAAAAAAA" (but with more A's) and switches from activity_main layout to graph_layout. As it should, that's precisely what I designed it to do.
Now, here's the problem. I also have a button in graph_layout with the ID, calc_button_3. When I click this button, it's supposed to print to the console "AAAAAAAAAAAAAAAAAAAAA2" (but with more A's) and then switch from graph_layout to activity_main. It doesn't do that, though. It prints to the console a little message that, "yes, you did click the button, here are all the details of how you clicked that button" (I'm paraphrasing), but it does not print "AAAAAAAAAAAAAAAAAAAAAAA2" to the console, nor does it switch back to activity_main. (If you're wondering, the AAAAA message is just to see whether the setOnClickListener functions are actually executing).
Speaking of which, here's what the setOnClickListener does for calc_button_3:
//final Context context = this;
calcButton3.setOnClickListener(new View.OnClickListener() { //I know I can use lambda funcitons, but I wanted to play it safe
#Override
public void onClick(View v) {
//Intent intent = new Intent(context, MainActivity.class); //This was one of the solutions I found online. It does not do anything.
//startActivity(intent);
System.out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2");
setContentView(R.layout.activity_main);
}
});
To be fair, I'm a step in the right direction. Before, this function made my app crash. Now, it just does nothing. So...that's a little better, and I'd like to thank the LayoutInflater class for making that possible. I'd also like to point out that I'm willing to supply you with any code or extra information you might want to see. I'd send the whole MainActivity.java file if I could, but I know from experience the longer I make my question, the less likely people are to answer, and it is a VERY long file.
I've scoured the internet for a solution to this, and while I've found people with a similar problem, none of their solutions worked for me.
Your help is greatly appreciated. Thank you.
Below, I will attach any code or additional info anyone in the comments asks me to give them:
You have to start a new activity using intent or if you want to use the same activity then use fragments. and replace fragment layout on button press. but you can not directly use setContentView();
All setContentView(R.layout.activity_main) does is inflate that layout file into its hierarchy of View objects, and display that in the current Activity. You're still in the same Activity, you've just changed its contents.
When you say you're doing this:
In activity_main, there's a button with the ID, graph_button_1. When I click it, it prints to the console "AAAAAAAAAAAAAAAAAAAA" (but with more A's) and switches from activity_main layout to graph_layout.
does that mean you're "switching" by calling setContentView there too, instead of starting a different Activity that displays graph_layout?
If so, and all your code for both layouts is in the same Activity, then your problem is probably related to the fact you're replacing your Views with a new set of objects when you call setContentView. If you set up your buttons like this:
// a Button from your current view hierarchy gets assigned to this at some point
val someButton: Button
// just use the lambda, it's literally the same as creating the object under the hood
someButton.setOnClickListener {
// do a thing
}
And then later you call setContentView(R.layout.some_layout), then whatever Button object someButton is referencing is no longer on the screen. So you can't see it, you can't click it. If you just inflated the same layout as before (creating an entirely seperate set of View objects) then there's another button in the same place - but you haven't set a click listener on it, so it doesn't do anything.
So if you are going to go replacing the view hierarchy like this, then you need to perform your View setup (like assigning click listeners) when you create those new views. If you just set things up when the Activity starts, then it's only applied to the view hierarchy in use at that moment. As soon as you replace it with setContentView, that stuff is gone.
So you could write functions that "switch" to one layout or the other by calling setContentView and then applying the click listeners. Generally speaking though, this isn't how you normally do things in Android. The old way would be to create separate Activities for each screen, a more modern approach is using Fragments which can be swapped out manually or by using something like the Navigation library.
Either way, both those approaches involve configuring your Activity or Fragment once during setup, making buttons do this or that, and then you're done. Everything's neatly separated and self-contained, instead of you having to swap views out and rewire everything according to the state you want to display. That's just complicating things, and it'll get much worse if you start adding more screens you have to juggle!
I'd recommend at least taking a look at the Fragments guide, or the Navigation component if you have time. The latter has more to learn, but it also handles a lot of complexity for you. It would help to at least have an understanding of the usual way of doing things, anyway!

Opening an activity within a View in Android

I've recently started developing Android Apps, and whilst the model is making more sense the more I look at it, I cannot do something (nor find any reference material on it) which to me seems quite simple.
I have an activity which has five buttons along the bottom, and a blank View taking up the rest of the screen. I want, upon clicking these buttons, for an activity to be opened in (and confined to) this view. I can get a new activity running without incident, but this opens in a new screen.
If anyone can show me an easy way to launch a (sub/child?) activity within a view which is defined in the parent activity's layout xml file - equally, it could be created in the parent activity - you'd really be doing me a favor!
I'd recommend taking a look at TabHost. The tabhost is an Activity itself, and the sub-views are all Actvities as well.
Here is a good tutorial that'll get you going very quickly. There is a more work to create (optional) icons for the tabs (also describe in the tutorial).
Hope this helps.
Edit* You mentioned buttons being at the bottom of the screen. Take a look at this SO Question
You can achieve that by using an ActivityGroup... here is a simple example which shows how to do it using a TabActivity:
http://web.archive.org/web/20100816175634/http://blog.henriklarsentoft.com/2010/07/android-tabactivity-nested-activities/
Of course, you will have to change the code since you are not using TabActivities. Just take a look at the getLocalActivityManager and getDecorView methods that is what you will be using.

Dynamically load layout in Android

My application requires 2 screens and for this I have created two different XML layout files using RelativeLayout. One layout file loads whenever I run my Activity. Now I want to load the second layout on to the same Activity , when user click on a button in OptionsMenu and also when user press Back button the first screen loads instead of exiting the application. So that i don't need to create another Intent in my application.
Ideally there should be two different activities present in your application.
You can add or remove a view component in a view but if you are looking for two completely different screens then i would suggest you to go for a new activity.
I dint get what you meant by "and also when user press Bakc button the first screen loads instead of exiting the application"
If you dont want to show the first screen just finish() the activity.
Did you try re-calling the setContentView?
Or you may prefer using the ViewFlipper,
Good example here.
I would suggest a rather simpler means.
Put both your layouts in the single XML and show/gone them appropriately as need be. I dont think u need anything more complicated :-)

Android Activities vs Views

Sorry, I know that this topic has been covered a bit. I've read the related posts and am still a bit confused. I am working on an app that while the prototype will have 3 main screens, it will eventually have dozens. Each screen will present either dynmically changing status or take user input. To visualize, it is required to be laid out similar to how MS Word or a typical PC is. It has a status bar at the top and a navigation bar at the bottom that is common to all screens (slight tweaks for some screens, like different icons) in the middle is what I would call a view pane that needs to be updated with a applicable layout.
The status, nav bar, and each screen are defined in their own layout xml file. For my first swag at it I just used a ViewFlipper and loaded the 3 screen layouts into it. However that means that currently I have one main Activity which will not be maintainable as I continue to add screens.
It feels right to me that each screen layout should have an associated Activity class that understands how to control that screen. I need to figure out how to load that into the center pane dynamically. However I thought I read in another post that using multiple Activities can be a CPU and RAM drain.
Currently I tried making one of the screens it's own Activity and kick that off from the main Activity by creating an Intent and than calling startActivity. However that causes the new screen Activity to reside on top of the main Activity. The interesting thing is that then pressing the back button dismissed that activity and returns me to the main.
So far I haven't figured out how to setup having a different Activity control what happens in the center pane.
If I continue down the multiple Activity path, should my main Activity be inheriting from ActivityGroup?
Are using View classes more applicable in this case?
I know this has been a long post. I'd appreciate any advice.
Thanks!
CB
As you noticed, Android will implicitly track a stack of started activities in a task, and the 'back' button ends the top one, reactivating the next one down. I would advise you to think about which kinds of things the user might expect the back button to do, and make it so that activities are separated along those lines.
I haven't played with ActivityGroup so I can't advise you there. If you go with completely separate activities, you can have them all use the same "shell" content view with the common nav/status bar. Have a superclass or utility class handle populating and managing that from there. Then use a a LayoutInflater (you can call getLayoutInflater()) to fill in the middle with your Activity-specific view.
If you want one of the activities to have multiple screens, you might still end up with a ViewFlipper in the center slot. Again, you want to have an Activity transition wherever you want the user to be able to go "back"; that also means you may NOT want to have a change of activities in cases where screens are closely related or part of the same logical thing-being-done. (You can override the back button's behavior, but unless you have a good reason to, it's best to just arrange the app so that Android's basic setup helps your app's UI rather than working at cross purposes.)
If you want to use activities in the fashion you talked about, you might look into using a tab activity. It actually works in the way you want, you just need to hide the tab widget and put your navigation bar there instead. Or, you could go a little deeper and make you own similar tab-like ActivityGroup like Walter mentioned if you have more time.
You could use a view pager with fragments to accomplish the flip between the different views but still allow your activity to have full control over it. The activity can control the menus while the fragment controls your viewing area. This way your back button will properly dismiss the activity containing all pages related to the activity instead of walking down the stack.

Modifying application workflow to use TabActivity

This question actually has two parts.
The first part:
I've been developing my first app for a couple of weeks now. I have 5 screens and everything seems well. However, I'm considering changing the app's navigation to a TabView.
I haven't delved much into it, but I'm hoping someone can save me a little bit of time. It seems that people don't generally place Activities inside each tab. They simply point the tab content to a View. This is where my major setbacks are. 1) I already have Activity classes full of code and 2) I can't quickly guess how the structure of an app using TabView looks. For example, where do I put the handler code for clicking a button on a View? Does it all just get dumped into the TabView Activity somehow?
What I would like is if you could please give me a quick synopsis of what I'm looking at doing, answers to any questions you think I may have, and point me toward some resources for creating TabView applications. A quick Google search really just shows me how to create a TabView Activity and add a couple tabs to it. The code doesn't go any deeper. For example, say I have a layout xml to show in one of my tab's content pane, where does the code go for clicking a button I have in that layout?
The second part:
I've added a TabActivity to wrap the Activities I currently have in. At the moment I have Activities populating the content of my tabs (though ultimately I'd like to do this in the most efficient fashion, which doesn't seem to be having Activities be tab content). I've noticed something rather annoying. My MAIN Activity is an Activity I wrote for my user to log in to their account. After logging in, they are taken to my Tab Activity. Here is what happens:
When I am on my Tab Activity and I "minimize" the app by clicking the Home button and then launch it again, I don't get taken back to the Tab Activity. I get taken to my log in Activity. Why? I don't have the launchMode of my Tab Activity set to singleInstance... or is it singleInstance by default? How can I make the app re-launch showing the Tab Activity (ideally by setting some parameter, assuming I'm doing something wrong, and not having to save this data off somewhere and reading it and programmatically telling it what to go to)?
Thank you for all your time and help
I don't have a comment on the advisability avoiding the use of sub-activities in TabActivity. As for handlers -- if you aren't going to embed views instead of activities, then all the android:onclick type handler settings in your layout XML will call methods on the TabActivity. This is because they go to methods on the views' Context, which is the generally the nearest containing Activity. If you want to split your code up further without using Activities, I believe you'll have to use findViewById calls on the tab content views after you've set them up, and bind the handlers manually from there in your code.

Categories

Resources