可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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"/>
回答1:
I played around a lot with this. I was finally able to reproduce your problem. I was missing the launchMode="singleTop"
for the MainActivity
, which was why I didn't see the behaviour earlier. Sorry about that.
If I add launchMode="singleTop"
to MainActivity
in the manifest, then I can reproduce the behaviour with code 2.
Using my suggested code, I was able to solve the problem:
Intent intent=new Intent(this,ListingActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
overridePendingTransition(R.animator.translate_left_to_right,
R.animator.translate_source_left_to_right);
However, I also needed to change the animation resource file translate_source_left_to_right.xml
to this:
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0%p"
android:toXDelta="100%p"
android:duration="400" />
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 :-)
回答2:
There is better solution to do that without using Intent.FLAG_ACTIVITY_*
or another FLAG
. You can try to add android:noHistory="boolean"
attribute in the AndroidManifest.xml
. By using this attribute, please understand my concept map below:
DESCRIPTIONS
Because of ActivityC
and ActivityD
(also called with last activities) has a true value, so they cannot back to MainActivity
, but they can back to ActivityA
and ActivityB
first. Also, ActivityA
and ActivityB
can back to MainActivity
. 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
(no FLAG
is needed):
If you want to go to A
from C
or from D
(in this case your activities, not the Activity on the concept map), call:
startActivity(new Intent(C.this, A.class));
See the concept map again, ActivityA
is chained with ActivityC
, and ActivityB
is chained with ActivityD
. Because of these activities look like chains, so you cannot call finish()
or pressing Back Key to go to MainActivity
directly. So that, call above code.
If you want to go to your ActivityA
from ActivityB
(in this case your activities, not the Activity on the concept map), you can call finish()
. By default, Android will make you back to previous activity without call finish()
when press the Back Key.
Usually, I don't need android:launchMode
attribute while using android:noHistory="boolean"
attribute.
Remember:
- Set your last
Activity
with android:noHistory="true"
in the manifest.
- Another
Activity
must be set with false value.
- Apply this attribute for all of your Activity.
As additional, here is how to use it inside your manifest:
<activity android:name=".MyActivity" android:noHistory="true" />
Add the animation
Override onResume()
method in your ActivityA
(in this case your activities, not the Activity on the concept map) and do your animation here:
@Override
public void onResume(){
super.onResume();
overridePendingTransition(R.anim.enterAnim, R.anim.exitAnim);
}
If doesn't work with onResume()
method, try to override the animation in the onStart()
method:
@Override
public void onStart(){
super.onStart();
overridePendingTransition(R.anim.enterAnim, R.anim.exitAnim);
}
回答3:
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.