I have a problem for implementing up navigation on an app with this navigation tree:
The standard implementation of the back button is fine.
The problem start when trying to implement the Up button.
What I expect:
when the user is on Detail 5 Activity and press the up button the app goes to List 3 Activity
when the user is on Detail 7 Activity and press the up button the app goes back to Home Activity
So in different terms, I'd like to have this behaviour on the back stack:
The Android documentation (Implementing Ancestral Navigation) advice to use the following code to handle up navigation:
Intent parentActivityIntent = new Intent(this, MyParentActivity.class);
parentActivityIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(parentActivityIntent);
finish();
But because the parent activity of the Detail Activity differs on the different navigation path I don't know which one it really is. So I can't call it in the Intent.
Is there a way to know the real parent activity in the Android back stack?
If not, is there a way to implement a correct up navigation in this app?
I will stick with my comment on Paul's answer:
The idea is to have a Stack of the last Parent Activities traversed. Example:
public static Stack<Class<?>> parents = new Stack<Class<?>>();
Now in all your parent activities (the activities that are considered parents -e.g. in your case: List and Home), you add this to their onCreate:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
parents.push(getClass());
//or better yet parents.push(getIntent()); as #jpardogo pointed
//of course change the other codes to make use of the Intent saved.
//... rest of your code
}
When you want to return to the Parent activity, you can use the following (according to your code):
Intent parentActivityIntent = new Intent(this, parents.pop());
parentActivityIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(parentActivityIntent);
finish();
I hope am right (:
That's a tricky question and in my opinion really shows the difficulties in coping with the UX decisions of Android for the "up button". Therefore, there's not a clear-cut answer to your problem.
I have two possible solutions for you.
1. Mimicking the back button behavior.
You could consider adding an extra to the intent for launching Detail from one of its various parents. This extra would inform those activities which activity they would need to launch when android.R.id.home is pressed.
This would effectively mean that your app "goes back" to its common ancestor, instead of simply relaunching Home.
Another way of implementing this may be simply executing onBackPressed() instead of launching Home with Intent.FLAG_ACTIVITY_CLEAR_TOP, but bear in mind that the associated animation would be different than a normal "up" action.
2. Skip intermediate activites and go home.
Some apps treat the "up button" as a "home button". You might want to consider having it simply always relaunch Home with Intent.FLAG_ACTIVITY_CLEAR_TOP.
this is an old post for sure, but as I was studying the SharedPreferences, I think it could be a possibility to stack this information within a sharedPreferences data, and to modify its value each time before going down the 2 parents.
Then by reading it, you should be able to directly know your parent, and this without having to build a whole class for that.
Related
I am beginner to android developing and I am dealing with a probably simply solvable problem.
I have a Main activity which is a menu and the user can click on of the items on menu. Then a new Activity is started using startActivity(new Intent("com.example.test.FIRSTITEM")); this activity starts a layout with few edittexts. I write something into them. Then to go back to the MainActivity (where the menu is) one have to press back button.
And now I want the behaviour that if I return to the Activity with edittexts, I want them to be in the same state - meaning the content wouldn't be cleared.
I've searched a lot and tried all options of android:launchMode="" (singleTop, singleInstance, singleTask).
I've also tried to use flags when starting new intent from MainActivity:
startActivity(new Intent("com.example.test.FIRSTITEM").setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP))
I've tried using onSavedInstanceState(Bundle bundle) but this one is never called when pressing back button (probably because the activity isn't really finished)
I am sure the answer is simple but I can't seem to find it. I must be missing some logic of how activities work.
Thank you for your help in advance.
I think this this could help you out.You can use
onsaveinstancestate() and onrestoreinstancestate().
I do totally agree with the Navigation below
Imagine that the Book detail is made in different instances of a BookDetailActivity.
The stack before pressing up in book2 detail is:
BookDetailActivity (Book 2 - You are here)
BookDetailActivity (Book 1)
AllBooksActivity
If I follow the guidelines I will use:
Intent parentActivityIntent = new Intent(this, AllBooksActivity.class);
parentActivityIntent.addFlags(
Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(parentActivityIntent);
finish();
But the big problem with this code is that BookDetailActivity (Book 1) is still alive!
Pressing back button after "up" would bring the detail of Book 1.
How can I kill all the BookDetailActivity that are between the original AllBooksActivity and the activity where I pressed up?
The related guidelines article notes the following:
Implementation Note: As a best practice, when implementing either Home
or Up, make sure to clear the back stack of any descendent screens.
For Home, the only remaining screen on the back stack should be the
home screen. For Up navigation, the current screen should be removed
from the back stack, unless Back navigates across screen hierarchies.
You can use the FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_NEW_TASK
intent flags together to achieve this.
Since you're doing that, BookDetailActivity1 should be closed by FLAG_ACTIVITY_CLEAR_TOP. The only way if it could be alive and shown on pressing Back is if it would have been started before AllBooksActivity.
As for not needing FLAG_ACTIVITY_NEW_TASK (suggested by android developer's answer):
When using this flag, if a task is already running for the activity
you are now starting, then a new activity will not be started;
instead, the current task will simply be brought to the front of the
screen with the state it was last in.
...so if your activity exists, it will not start a new task.
ok , there are multiple ways to do such a thing. here's one of them:
however , i would suggest that instead of opening the first activity as if it's a new one , simply finish the current one and the one before it .
in order to do it , call each new activity with startActivityForResult , and set the result for each of the activities to some value that says you wish to return to the first activity .
you can even set the value to be the class canonical name , and make a base activity that will handle all of those requests automatically so that you won't need to handle it .
in any case , i think you made a mistake by using Intent.FLAG_ACTIVITY_NEW_TASK since it creates a new task , so the previous one still exists . try to read the available intents flags for more information:
http://developer.android.com/reference/android/content/Intent.html
I am trying to close a whole stack of activities using the way described here:
How to kill an application with all its activities?
Namely, each activity starts the other one with startActivityForResult, and in onActivityResult calls finish() to close itself together with the activity it opened.
The problem is that the activities in the task still seem to repaint themselves at least once before they close, and this doesn't look good. After closing the topmost activity one sees all previously opened activities like in a very fast slideshow.
How can one avoid this graphical issue?
EDIT: I need that if the user presses HOME button and then presses the app's icon in launcher, he returns to the current state of the stack, not to the very first activity again. So, from what I understand, with such a requirement I can't finish() activities before starting next ones.
That's native behaviour, intended to aid in user Experience. When an Activity is started with startActivityForResult and then finishes, it will (on devices that allow fancy animations) automatically slide away. That helps people not get surprised by the screen suddenly changing.
You could try starting the Activities without startActivityForResult and handling the passing of data to and from Activities manually, then handle how/when Activities finish() and which Activity they pass back to. You might find you implement something where Activities actually pass forward to the appropriate Activity all the time, rather than back to an Activity on the stack.
Intent intent = new Intent();
intent.setClass(getApplicationContext(),
PhoneListCheckboxAES.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
If u give like this when u are starting the next activity then the graphical problems won't occur
I would like to create a button in my game for the user. The button will quit the application.
Please can someone tell me if there is a way to do this.
Thanks.
Edit:
I have an activity which uses another activity with a class that extends Android.app.Application using set and get methods.
Simply using the back button switches the activities until it goes to the beginning.
I go in between these classes 20 times.
Thats why I needed a back button. But I guess there isn't so I will have to do it the long way and set everything back to the first state on quit. Thanks
There is not a way to make quit button. And there is good reason for that because the Android experience is having the back button do the closing. So you just to make the back button exit back to the home page. To do that you need make sure that your current activity is the only one oh the history stack. Then you can create a button that just calls finish(). Hope the detail explanation helps.
You probably want to mange the activity stack better.
If you look at Activity and Task Design Guidelines
it might help.
Setting the flags when you start each activity is probably the key, code such as
Intent i = new Intent(this, Whatever.class);
i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(i);
will limit the number of instances of 'whatever' to one only. ( A different flag might be more appropriate for you depending on how you want your app to run, read up about them all)
Try this:
public void quit(View view) {
if(Build.VERSION.SDK_INT>=16 && Build.VERSION.SDK_INT<21){
finishAffinity();
} else if(Build.VERSION.SDK_INT>=21){
finishAndRemoveTask();
}
}
If I read your full question, you are looking for a Reset button not exactly a quit button. I had a similar issue... the next and previous takes only one step back at a time. I wanted to go back to the very beginning. The way I acheived this is to have a class to manage the pseudocursor.. basically an int that represented which resource to pick (I used a singleton). In the main activity's Menu (android.view.Menu), I added a reset/go to beginning option. This will simply reset the pseudocursor. In my activity class's onResume(), I had the code to get the resource from the singleton. So no extra coding was required there.
Instead of having this option under Menu, you can always have a button in UI which does the same thing.
Actually i m little bit confused in Intent.
Suppose i have three activities.
A,b,c and in activity A i have exit button. When i click on exit button my application finishes. I have one more button in A which is next button. Which take me to new activity.
and in activity B i have two buttons next and back, and in activity C also i have two button out of which first takes me to A and Back button.
now i'm on C activity and want to go to A. where when i press exit it again takes me back to C instead of finish the application.
Why is this happening?
Not really answering your question but your Android application just shouldn't have an Exit button. It's not necessary.
This blog post by Reto Meyer - a Google employee who works on Android - explains it well. This passage from it might be significant in relation to your problem:
In most cases the exit button simply calls Activity.finish. This is exactly equivalent to hitting the back button. Exactly.
There is no Exit function in Android.
You probably want to bring up the Home application by it's corresponding Intent:
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Exit button or not, Activity.finish only applies to the current activity and you are dealing with three different activities. Finishing activity A is simply taking you back in your stack to the previous activity C.
Check out the documentation on Activities and Tasks, launch modes, and clearing the stack for some explanation of what's going on in your example and what you can do to alter the behavior. I've always thought these sections of the Android documentation need to be enhanced or further explained but hopefully it will help a little.