Clearing the Android back stack - android

I'm trying to do something similar to this question.
I've got a main app A, and sub-apps B and C. B is a searchable dictionary, and C is a definition, so if you search for many words, you can end up with the stack looking like A > B > C > B > B > C > B > C > C > C... etc
Whenever I go back, I'd like to go back to the original B, so I want the back stack to basically stay at A > B all the time.
I've currently got it set up using an Intent so when the back button is pressed from C, it goes to a new instance of B, but that's obviously not what I want.
Ideas?

Shouldn't hitting BACK from C take you to the original B? So the stack should look like:
A>
B>
C<
B>
C>
C<
C<
B<
A
with > going to the next activity, and < being the back button?
You could override onBackPressed for all the activities, so for C it loads a new B, B it loads a new A, and A you would do moveTaskToBack(true);, but that's less of a solution and more of a hack to make it work.
Try to use onResume so that B comes up like it would on default. Set any pertinent variables to what they are in a new activity. If you only want this when you're coming from C, have a class boolean that is set to true when C is loaded, and check it in onResume or onRestart. If it's true, set everything to default/blank, and set the boolean to false. If not, load it how it was (this is if they hit home and come back to the app, basically). I'm not at my work desk, but I think you'll want:
#Override
public void onResume() {
super.onResume();
if(fromC == true){
//Set all variables to load default dictionary
fromC = false;
}
}
}
This should make the original B act like a new B.
Or instead, you could do it the easy way, and when you call the intent to load a new B like this:
startActivity(getIntent());
finish();
That'll make there only be one B. Making it load as a blank when you go back is a little bit different and requires class variables, or some other tricky trick that I am thinking of. This is something like what you'll want to do: .zip of small sample
If you can get your code reworked to something like that almost (where you can use the appropriate variables to set up things to work right if that makes any sense).

#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (splash.sdk < 5 && keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
onBackPressed();
}
return super.onKeyDown(keyCode, event);
}
//This will make the back button exit the app to the home screen.
#Override
public void onBackPressed() {
moveTaskToBack(true);
return;
}

You can set an Intent flag to do this. Say you are in Activity C and you want to call Activity B: you add a flag to the Intent called FLAG_ACTIVITY_CLEAR_TOP. So:
class C extends Activity {
//...
private void gotob() {
Intent go = new Intent(this, B.class);
go.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(go);
}
//...
}
What this does is either to go to the top instance of B in the back stack (and clear everything else off the top), or create a new instance if none exists. I haven't worked out if there is a way to do this with launch flags though—there are some similar modes but I don't think any are identical.

Related

Shared Element Transition is broken between three or more activities

Problem
I want to achieve shared element transition between Activity A and B, and between Activity B and C.
I did everything based on the android transition documentation.
There is no problem between:
A => B => back to A
A => B and B => C => back to B
But if I do:
A => B and B => C => back to B => back to A
The last step will not have any shared element transition (actually not only shared element transition, even there is only fading it could be lost).
I have been looking for solutions everywhere, but it seems everybody only needs A => B (and B => A) shared element transition but doesn't care any more transitions from B => C and back to A.
Example
See an example I created based on android's animation samples, where Activity A = MainActivity, B = DetailActivity, C = DetailDetailActivity. Clicking the button on Activity B will navigate to Activity C.
Because while executing C => B, it will re-construct a new EnterTransitionCoordinator for B, replacing the old one contains the correct mPendingExitNames which it is important to indicate views need to be transitioned between A and B.
public boolean startExitBackTransition(final Activity activity) {
ArrayList<String> pendingExitNames = getPendingExitNames(); // here
if (pendingExitNames == null || mCalledExitCoordinator != null) {
return false;
} else {
// ...
}
}
The solution seems to be a little bit tricky. You can refer to ThreeActivityTransitionDemo and pay attention to the SharedElementUtils.
Add this to Activity B
#Override
protected void onStop() {
if(Build.VERSION.SDK_INT == Build.VERSION_CODES.Q && !isFinishing()){
new Instrumentation().callActivityOnSaveInstanceState(this, new Bundle());
}
super.onStop();
}

Using noHistory=true but opening previous activity when Back is pressed

I've been use
android:noHistory="true"
in my code so that I don't have many activities open at the same time.
The problem is the following:
Consider that I navigate navigate from Activity A (HomePage) to Activity B (noHistory=true) to Activity C. From Activity C, if I press the (hardware) back button, it takes me back to Activity A, not B. This is android:noHistory="true" , right? Is there a way to go back to Activity B and load it from scratch instead of going all the way back to Activity A?
Thanks!
You could just use something like this to go 'back' to any activity you'd like.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if(keyCode == KeyEvent.KEYCODE_BACK)
{
Intent intent = new Intent(startActivity.this, returnActivity.class);
startActivity(intent);
return true;
}
return false;
}
I ended up doing #Chandrakanth's method (thanks!); I passed extras to Activity C that will tell it what activity B to open when I press the back button.

How to implement the following?

Given:
6 activities. (A, B, C, D, E, F)
Each activity consists of several edittexts or a camera implementation and a next button to goto next activity (The activity which is going to be opened depends on the value entered by the user).
If edittexts are displayable or not comes from the server.
Incase there are no edittexts on the layout then only next button is shown.
Flow of the application: A->B->C(->D)->E->F
The Activity D opens only when a certain condition is met in activity C.
Todo:
Incase, The activity contains no edittext and only next button i should be able to skip this activity.
If the flow of my application is like: A->B->C->E->F Then when i press hard back the flow should be F->E->C->B->A
If the flow of my application is like: A->B->C->D->E->F Then when i press hard back the flow should be F->E->C->B->A
If the flow of my application is like: A->C->D->E->F Here we skipped B because there are no views in Activity B, When i press hard back the flow should be F->E->C->A
what i did:
To skip the activity when no fields are available inside onCreate(), I am checking if any field is displayable if no then i add the activity name in a stack if it is not present in it and then open the next activity.
// Block for skipping this screen
if (skipScreen) {
Intent i = new Intent(B.this, C.class);
startActivity(i);
finish();
} else {
if (!Constants.st.contains(B.class)) {
Constants.st.push(B.class);
}
}
And when i press back from an activity i pop() the name of that activity from the stack and peek() at the top of the stack and jump to that activity.
public void onBackPressed() {
super.onBackPressed();
Constants.st.pop();
Intent i = null;
if (Constants.st.isEmpty()) {
i = new Intent(B.this, A.class);
} else {
Class<Activity> jumpTo = Constants.st.peek();
i = new Intent(B.this, jumpTo);
}
startActivity(i);
finish();
}
I think the statePattern will be very helpfull. Here is a short tutorial.

Customizing Back Stack in Android Activities

Consider there is one activity, named Activity S.
Then there will be many activities, say 10 activities, named A, B, C, ..., J.
How can I achieve this:
From those A--J activities, when the back button is pressed, always go back to activity S.
Regardless of the ordering or how the activities are created.
For example:
Starting from S, go to B, then D, then G.
In activity G, press back button, and will go back to S.
== EDIT ==
Should I use Activity.finish() method when leaving all A--J activities ?
You could accomplish this in different ways depending on the exact result you desire. You could add the following line to your <activity> tags in your manifest.xml for those Activities
android:noHistory="true"
or use an Intent flag when overrdiing onBackPressed() in each
#Override
public void onBackPressed()
{
Intent i = new Intent(CurrentActivity.this, S.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);`
startActivity(i);
super.onBackPressed();
}
this will clear the other Activities from the stack and return you to S.
If you want to keep the Activities on the stack while returning to S then you can change the flag used
#Override
public void onBackPressed()
{
Intent i = new Intent(CurrentActivity.this, S.class);
i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);`
startActivity(i);
super.onBackPressed();
}
The last way will bring S to the front and keep the other Activities on the stack which I don't think is what you want but just another option. You will probably want one of the first two ways.
You have to do like this to achieve, Set a flag that will Clear every activity from stack and pass intent to S.class, like this
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
Intent intent=new Intent(this,S.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}

How to clear stack history?

Consider am having an application containing activity A,B,C. A is launched from the launcher and B is launched from A. B has a button. My requirement is on clicking button on B the present history of the activity Stack A->B should clear and the history stack must contain only C. Is it possible to do ? If so plz advise me...
Thanks in advance !
Although tedious, this can be done by launching using the Activity methods startActivityForResult(), setResult(), finish(), and onActivityResult().
In pseudo-code:
A: startActivityForResult(B)
B: startActivityForResult(C)
C: startActivity(D); setResult(CLEAR); finish()
D: ...
B: (onActivityResult) setResult(CLEAR); finish()
A: (onActivityResult) finish()
If you're willing to change your architecture a bit a more "natural" way to do this is to use FLAG_ACTIVITY_CLEAR_TOP for an easy way to go from A, B, C to just A.
A third way is to set A, B, and C to use noHistory, but then you would lose the ability to back out of C into B or A.
My "solution" is to override behaviour of Back button in activity C, so that it goes to phone launcher, not back the activity stack. This way, activities A and B remain on the back stack, but user has no way to navigate back to them. So the net result is same as if activity C was root activity.
/**
* Override "Back" key on Android 1.6
* Don't want user going back to Login or Register forms.
*/
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
goHome();
return true;
}
return super.onKeyDown(keyCode, event);
}
/**
* Override "Back" key on Android 2.0 and later
*/
#Override
public void onBackPressed() {
goHome();
}
private void goHome() {
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
}

Categories

Resources