Ashwin
Ashwin

Reputation: 13547

Is transition animation not possible when using FLAG_ACTIVITY_CLEAR_TOP?

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"/>

Upvotes: 8

Views: 3825

Answers (4)

Sahil Bansal
Sahil Bansal

Reputation: 729

This happens because transition donot have object to start transition and to end transition When we use clear stack then all activity get cleared and transition will left without nothing so have done this by implementing following line in my style code

But use this causiously

<item name="android:windowDisablePreview">true</item>

Upvotes: 1

Sira Lam
Sira Lam

Reputation: 5367

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.

Upvotes: 0

David Wasser
David Wasser

Reputation: 95626

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 :-)

Upvotes: 5

Anggrayudi H
Anggrayudi H

Reputation: 15165

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:

enter image description here

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);
}

Upvotes: 2

Related Questions