I have a MainActivity
(which has launchMode=singleTop) from which I go to other activities, For eg B
and C
. Now, I want to navigate back to MainActivity
on some button click in B
and C
. And also I want transition animation.
Here is the code
CODE 1
Intent intent=new Intent(this,MainActivity.class);
Bundle animation= ActivityOptions.makeCustomAnimation(getApplicationContext(), R.animator.translate_left_to_right, R.animator.translate_source_left_to_right).toBundle();
startActivity(intent,animation);
finish();
The above code works fine, EXCEPT the fact that a new instance of MainActivity
is created on top of the old one! I don't want that to happen. So, after a bit of research I tried the below code
CODE 2
Intent intent=new Intent(this,ListingActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Bundle animation= ActivityOptions.makeCustomAnimation(getApplicationContext(), R.animator.translate_left_to_right, R.animator.translate_source_left_to_right).toBundle();
startActivity(intent,animation);
finish();
This code seemed to remove the problem of creating a new instance of the activity as the flag FLAG_ACTIVITY_CLEAR_TOP
took care of it. BUT, now the transition animation does not seem to work!
Does the flag FLAG_ACTIVITY_CLEAR_TOP
not allow any animation? What is the solution to my problem? I need both animation transition and also that a new instance of the MainActivity
should NOT be created.
EDIT
This seems to do the trick as suggested by David Wasser.
Intent intent=new Intent(this,ListingActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
finish();
overridePendingTransition(R.animator.translate_left_to_right,R.animator.translate_source_left_to_right);
BUT the animation is not smooth. There is a glitch in the animation. I think that is because the activity (B or C) gets destroyed before the animation is complete. I am not sure though
Posting the animations files
translate_left_to_right.xml
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="-100%p"
android:toXDelta="0%p"
android:duration="400"/>
translate_right_to_left.xml
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="100%p"
android:toXDelta="0"
android:duration="400"/>
translate_source_left_to_right.xml
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0%p"
android:toXDelta="50%p"
android:duration="400"/>
translate_source_right_to_left.xml
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:toXDelta="-50%p"
android:duration="400"/>
There is better solution to do that without using
Intent.FLAG_ACTIVITY_*
or anotherFLAG
. You can try to addandroid:noHistory="boolean"
attribute in theAndroidManifest.xml
. By using this attribute, please understand my concept map below:DESCRIPTIONS
Because of
ActivityC
andActivityD
(also called with last activities) has a true value, so they cannot back toMainActivity
, but they can back toActivityA
andActivityB
first. Also,ActivityA
andActivityB
can back toMainActivity
. So, no new instance will be created.After you declared the value in the manifest, you only need to call the following code to open the next
Activity
(noFLAG
is needed):If you want to go to
A
fromC
or fromD
(in this case your activities, not the Activity on the concept map), call:See the concept map again,
ActivityA
is chained withActivityC
, andActivityB
is chained withActivityD
. Because of these activities look like chains, so you cannot callfinish()
or pressing Back Key to go toMainActivity
directly. So that, call above code.If you want to go to your
ActivityA
fromActivityB
(in this case your activities, not the Activity on the concept map), you can callfinish()
. By default, Android will make you back to previous activity without callfinish()
when press the Back Key.Usually, I don't need
android:launchMode
attribute while usingandroid:noHistory="boolean"
attribute.Remember:
Activity
withandroid:noHistory="true"
in the manifest.Activity
must be set with false value.As additional, here is how to use it inside your manifest:
Add the animation
Override
onResume()
method in yourActivityA
(in this case your activities, not the Activity on the concept map) and do your animation here:If doesn't work with
onResume()
method, try to override the animation in theonStart()
method:I have exactly the same issue with you.
However, using @David Wasser 's solution will sacrifice the parallax effect during transition. May be some developers don't want such behavior as well.
I then find another solution by checking if your MainActivity exists in backstack or not. Please check my answer here below:
how to check if activity is still in the stack?
Note that my solution will disable the animation, using system's default animation (same as
finish()
). But since you are really shutting down the current activity, I think this is more natural.I played around a lot with this. I was finally able to reproduce your problem. I was missing the
launchMode="singleTop"
for theMainActivity
, which was why I didn't see the behaviour earlier. Sorry about that.If I add
launchMode="singleTop"
toMainActivity
in the manifest, then I can reproduce the behaviour with code 2.Using my suggested code, I was able to solve the problem:
However, I also needed to change the animation resource file
translate_source_left_to_right.xml
to this:This is what was causing the "glitch" in the animation. You had the incoming activity animate from -100% to 0% and the outgoing activity animate from 0% to 50% over the same period of time. So the outgoing activity moves half the screen width and then stops. I changed the outgoing animation so that it animates from 0% to 100% and now you see both views animating over the complete width (which I think is what you want).
Thanks for the challenge :-)