Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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"/>
like image 335
Ashwin Avatar asked Jan 27 '15 17:01

Ashwin


2 Answers

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

like image 63
David Wasser Avatar answered Nov 13 '22 12:11

David Wasser


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);
}
like image 1
Anggrayudi H Avatar answered Nov 13 '22 13:11

Anggrayudi H