31

I'm working on making an application more Material and I'm just stuck on how to implement some shared element transitions. I have an activity A that starts another B and then calls finish() in order to remove it from the back stack. In my case I have an element I want to share between the two activities, but once it is passed from A to B, A no longer matters. If I don't call finish() after startActivity(ctx,intent, bundle) the exit/enter animation works perfectly. However, if I do call finish, there's a really ugly flicker before the animation starts.

Is there something I'm overlooking or is it just not possible to do what I am trying to do?

l-l
  • 3,804
  • 6
  • 36
  • 42
F.A.
  • 602
  • 1
  • 7
  • 15

6 Answers6

31

You can finish your activity in the onStop function, if you only want this to happen when you transition from A to B then create a flag and set it after you call startActivity(ctx,intent, bundle):

@Override
public void onStop() {
    super.onStop();
    if(mShouldFinish)
         finish();
}

Make sure when you are done with activity B to call finish() and not finishAfterTranstion() since activity A is no longer there

After finishing the activity A, shared element in B might hang in screen if you press back. Set transitionName to null in ActivityB.onEnterAnimationComplete to avoid this.

Mahendran
  • 2,719
  • 5
  • 28
  • 50
l-l
  • 3,804
  • 6
  • 36
  • 42
  • 1
    This does not work for me, the shared element transition is not correct when I do this. Everything is fine if I don't finish Activity A but I want to do so after the transition is finished. Can't get this to work. – Gabor Peto May 10 '17 at 07:11
  • 1
    Only this solution worked when using shared elements transition – Antonis Radz Mar 08 '19 at 12:02
  • It almost was great solution for me... but it doesn't work on huawei :) – Demigod Mar 20 '19 at 11:26
31

UPDATE

Much better and simpler way

ActivityCompat. finishAfterTransition(this);

<3 support library.

ksarmalkar
  • 1,884
  • 1
  • 16
  • 21
  • 2
    I cant seem to find `finishWithTransition`. So I tried `finishAfterTransition` and did not work either. – guness Aug 27 '15 at 13:29
  • Its in support library. Also try bumping your targetSDK version – ksarmalkar Sep 02 '15 at 17:51
  • The call is actually: ActivityCompat.finishAfterTransition(this); Just tested and it works great. – Darren B Sep 25 '15 at 19:13
  • 18
    this still causes flickering for me using a shared element. – xsorifc28 Dec 04 '15 at 22:34
  • what do you mean by flickering ? can you upload some gif some where and post link here – ksarmalkar Dec 07 '15 at 19:38
  • 8
    @ksarmalkar, `finishAfterTransition` doesn't call `finish` *after* the transition is complete; it just calls `finish` immediately. So if you are transitioning from Activity A to B, and B fades in, then A is gone so the Home screen bleeds through (or possibly another Activity). Note: this seems to happen only when using shared transitions. – David Murdoch Dec 17 '15 at 18:49
  • `finishAfterTransition` is just calls after the activity transition, the shared elements is a different transition and you need to do the ```boolean```trick. – extmkv Aug 06 '17 at 21:07
  • `ActivityCompat. finishAfterTransition(this);` is buggy, sometimes it is finishing, sometimes not, sometimes it is even causing crashes...... – Antonis Radz Apr 15 '20 at 11:46
7

This is maybe late but I had the same issue. What worked for me is:

supportFinishAfterTransition();

This is included in the support library and works like charm.

PS: you don't needto call finish() when you call supportFinishAfterTransition() .

ahmed_khan_89
  • 2,755
  • 26
  • 49
2

Try out finishAfterTransition() method in 5.0 and above you can finish the activity after the exit transition occurs.

Karthik Rk
  • 707
  • 1
  • 10
  • 19
2

If you use ActivityOptions.makeSceneTransitionAnimation(Activity, android.view.View, String) to make your transition you should use its callback method in Activity B to finish Activity A.

    setEnterSharedElementCallback(new SharedElementCallback() {
        @Override
        public void onSharedElementEnd(List<String> sharedElementNames, List<View> sharedElements, List<View> sharedElementSnapshots) {
            super.onSharedElementEnd(sharedElementNames, sharedElements, sharedElementSnapshots);
                // finish Activity A

        }
    });
6rchid
  • 1,074
  • 14
  • 19
2

I've written a variation of this answer which I find a bit more elegant as you don't need a field.
This is still far from ideal but it works in my use case which is basically a splash screen with a transition to the next screen and I want the splash screen to be closed right away. This works because onStop is called when the activity is not visible anymore, thus at that point we can actually close it without causing artifacts (in this case this blinking / flickering)

lifecycle.addObserver(object : LifecycleEventObserver {
    override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
        if (event == Lifecycle.Event.ON_STOP) {
            lifecycle.removeObserver(this)
            finish()
        }
    }
})
florianmski
  • 5,603
  • 1
  • 17
  • 14