30

I have two activities in the stack, in order to show them I use FLAG_ACTIVITY_REORDER_TO_FRONT. So far so good, the problem comes when I want to bring the activity with an animation using overridePendingTransition.

Intent i = new Intent(ActivityA.this, ActivityB.class);
i.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); 
ActivityA.this.startActivity(i);
overridePendingTransition(R.anim.transition_to_right, R.anim.transition_to_left);

The transition is not shown, however, if the flag is not added to the intent (removing line 2) then there is no problem.

Is it possible to bring an activity to front with an animation?

Thanks a lot!

thiagolr
  • 6,703
  • 6
  • 37
  • 59
Daniel
  • 301
  • 1
  • 3
  • 3

8 Answers8

43

Actually the right solution when using REORDER_TO_FRONT is to call overridePendingTransition in the method onNewIntent() of the activity you are going to open.

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
}

replace with your transitions.

If you need to selectively replace the transition you can add an extra in your intent and check it in the onNewIntent() to decide what to do.

This is not suitable if you don't know the transition that will be opened (if you don't specify it explicitly for example) but otherwise is the right solution.

Daniele Segato
  • 10,371
  • 4
  • 55
  • 80
  • 8
    The only proper solution. Should be accepted answer. – tomrozb Sep 01 '14 at 19:21
  • 1
    I wish I know why some people downvoted my answer, this is, as tomrozb said, the only proper solution – Daniele Segato Oct 23 '14 at 10:01
  • 2
    Since `onNewIntent` isn't called when the activity is created, you'll have to also do `overridePendingTransition` where you start the activity. – androidguy Jun 07 '18 at 02:14
  • That i obvious :-) i never said you need to do it in only one place. And by the way: now navigation Controller should be used – Daniele Segato Jun 07 '18 at 04:31
  • I spent hours looking for a solution. Cheers – Oyeme May 12 '19 at 08:51
  • Does `onNewIntent` get called on the first load of the Activity? If not, then the animation won't show on the first load. – seekingStillness Jun 02 '20 at 01:34
  • @seekingStillness no it does not, `onNewIntent()` is only for when you re-open an activity with a new intent. For the fist time you can do on `onCreate()` only if `savedInstanceState` is `null` (be sure to use `saveInstanceState()` so that it will not be `null` after the first time) – Daniele Segato Jun 03 '20 at 06:47
35

I ran into this same problem. The trick is to override the transition in the onResume() callback.

@Override
public void onResume() {
    super.onResume();
    overridePendingTransition(R.anim.transition_to_right, R.anim.transition_to_left);
}
bradley4
  • 3,407
  • 5
  • 32
  • 41
  • by doing it in onResume(). The effect is not at all smooth when the first activity is brought on top , it appears with a jerk – Ravi Jun 21 '13 at 12:26
  • this works for me when I start a new activity from service, and need to override pending transaition! – cwhsu Mar 01 '14 at 07:24
  • 2
    This suggestion is not correct. onResume is called in many occasion that have nothing to do with a new intent being used. The correct solution is the one I pointed out: do it in onNewIntent() method – Daniele Segato Jul 31 '14 at 00:06
5

for me, the solution was to make sure it's ran in the UI thread

runOnUiThread(new Runnable() {
            public void run() {
                startActivity(new Intent(ActivityOne.this, ActivityTwo.class));
                overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
            }
        });

        finish();
K-RAD
  • 465
  • 6
  • 11
3

I got the same problem. I suggest you check your AndroidManifest.xml to make sure ActivityA and ActivityB both have no set Theme.Translucent.NoTitleBar, this theme contains "android:windowIsTranslucent"=true cause the issue.

Hope this help you.

huangxin
  • 480
  • 4
  • 6
2

Calling

overridePendingTransition(R.anim.transition_to_right, R.anim.transition_to_left);

after finish(); of the closing activity worked for me.

finish();
overridePendingTransition(R.anim.transition_to_right, R.anim.transition_to_left);

It's better than calling onResume, because it makes the activity more independent about the enter and exit animations:


Calling after finish of sender activity:

Activity A ---Enter Transition 1 (on A)---> Activity B ---Enter Transition 2 (on B)---> Activity C

Activity A <---Exit Transition 1 (on B)--- Activity B <---Exit Transition 2 (on C)--- Activity C

Activity A ---Enter Transition 1 (on A)---> Activity C ---Enter Transition 3 (on C)---> Activity B

Activity A <---Exit Transition 3 (on C)--- Activity C <---Exit Transition 2 (on B)--- Activity B



Calling on onResume of receiver activity:

Activity A ---Enter Transition 1 (on B)---> Activity B ---Enter Transition 2 (on C)---> Activity C

Activity A <---Enter Transition 1 (on A)--- Activity B <---Enter Transition 2 (on B)--- Activity C

Activity A ---Enter Transition 3 (on C)---> Activity C ---Enter Transition 2 (on B)---> Activity B

Activity A <---Enter Transition 1 (on A)--- Activity C <---Enter Transition 3 (on C)--- Activity B

Here the onResume animation always have to be the same no matter which sender activity it is, instead the first approach, where you can custom the animation easily.

Leonardo Cardoso
  • 1,174
  • 2
  • 12
  • 22
  • Original question didn't state the original activity is being finished. This answer isn't relevant if you're starting one without finishing, – androidguy Jun 07 '18 at 01:57
1

My colleague ran into this issue and he managed to solve it by adding the minimum SDK attribute (5 and over) to it.

since this feature was available since api 5, enforcing the usage of a higher sdk level did the trick for us.

Royi Benyossef
  • 769
  • 5
  • 18
0

How about creating animation in the onCreate() or onStart() of the second activity.

GSree
  • 2,872
  • 1
  • 20
  • 25
  • Hmm...sounds like a good idea! thanks a lot. Im going to learn how to deal with animations and try that. – Daniel Jan 09 '11 at 20:10
  • @Daniel check out APIDemos (provided along with android framework) com.example.android.apis.animation.Rotation3dAnimation.java and how it is used in Transition3D.java. Should give you good insight. – GSree Jan 10 '11 at 00:06
  • Thanks GSree for your help! I have tried to launch a slide-out animation in the onPause() from activity A, and a slide-in in the onResume() from activity B. It was a nice idea, and it work out, but it is not smooth enough, as you can see a kind of black blink, because the animations are not excuted at the same time. I keep working on this, if I find a good solution I will let it know. – Daniel Jan 10 '11 at 15:35
  • Good to know that. Let me know how it goes – GSree Jan 10 '11 at 22:10
  • Why would you do that when onNewIntent() method has been created just for that reason? onCreate(), onStart(), and onResume() serve completely different purposes – Daniele Segato Sep 02 '14 at 22:24
-2

I did something similar and i did as follows:

private Stack<String> stack;
ViewAnimator mViewAnimator;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mViewAnimator = new ViewAnimator(this);
    if (stack == null) stack = new Stack<String>();
    push("FirstStackActivity", new Intent(this, FirstStackActivity.class));
}

@Override
public void finishFromChild(Activity child) {
    pop();
}

@Override
public void onBackPressed() {
    pop();
}

public void push(String id, Intent intent) {
    Window window = getLocalActivityManager().startActivity(id, intent);
    if (window != null) {
        stack.push(id);
        View view = window.getDecorView();
        mViewAnimator.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_in));
        mViewAnimator.setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_out));            
        mViewAnimator.addView(view);
        mViewAnimator.showNext();
        setContentView(mViewAnimator);
    }
}

public void pop() {
    if (stack.size() == 1) finish();
    if (stack.size() > 0) {
        LocalActivityManager manager = getLocalActivityManager();   
        Intent lastIntent = manager.getActivity(stack.peek()).getIntent();
        Window newWindow = manager.startActivity(stack.peek(), lastIntent);
        View view = newWindow.getDecorView();
        mViewAnimator.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_right_in));
        mViewAnimator.setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.push_right_out));
        mViewAnimator.showPrevious();
        mViewAnimator.removeView(view);
    }
    destroy(stack.pop());
}


/**
 * BugFix official
 * @param id
 * @return
 */
public boolean destroy(String id) {
    final LocalActivityManager activityManager = getLocalActivityManager();
    if (activityManager != null) {
        activityManager.destroyActivity(id, false);
        try {
            final Field mActivitiesField = LocalActivityManager.class.getDeclaredField("mActivities");
            if (mActivitiesField != null) {
                mActivitiesField.setAccessible(true);
                @SuppressWarnings("unchecked")
                final Map<String, Object> mActivities = (Map<String, Object>) mActivitiesField.get(activityManager);
                if (mActivities != null) {
                    mActivities.remove(id);
                }
                final Field mActivityArrayField = LocalActivityManager.class.getDeclaredField("mActivityArray");
                if (mActivityArrayField != null) {
                    mActivityArrayField.setAccessible(true);
                    @SuppressWarnings("unchecked")
                    final ArrayList<Object> mActivityArray = (ArrayList<Object>) mActivityArrayField.get(activityManager);
                    if (mActivityArray != null) {
                        for (Object record : mActivityArray) {
                            final Field idField = record.getClass().getDeclaredField("id");
                            if (idField != null) {
                                idField.setAccessible(true);
                                final String _id = (String) idField.get(record);
                                if (id.equals(_id)) {
                                    mActivityArray.remove(record);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }
    return false;
}
ademar111190
  • 13,115
  • 12
  • 74
  • 101