4

Got this in only android-10(Q) and works fine in android pie and below api levels. I was trying to work with sharedElement transition. From a recyclerView item to new activity. It works fine when i work with two activities that is., From Activity A -> Activity B and returning from Activity B -> Activity A. While working with three activities A,B & C.

For two activities

Activity A -> Activity B through sharedElement transition and Activity B -> Activity C without any transitions. After this Activity C -> Activity B -> Activity A.

For three Activities

SharedElement transition is not working from Activity B -> Activity A.

seenukarthi
  • 8,241
  • 10
  • 47
  • 68

3 Answers3

3

You can try adding these codes in ActivityB's onStop method

override fun onStop() {
    if (!isFinishing && Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {    
        Instrumentation().callActivityOnSaveInstanceState(this, Bundle())
    }
    super.onStop()
}

I use the method to avoid this issue.

ppxpp
  • 31
  • 3
  • 1
    Thanks, this seems to work if there's no transition from B->C but only from A->B. So it partially solves the issue. Did you happen to find a solution that would also work for multiple shared element transitions between 3 and more activities? – user1071762 Jun 24 '20 at 08:31
1

I actually encountered same issue like OP on Android 10+ (11 dev preview also suffers from it). I spent like 2 weeks on it so I'll try to summarize my findings and a hack how I managed to fix it in my project.

So I found out that if call the code that ppxpp posted as an answer it does help when when the screen rotates (or any other config change).

Then I found out it's better to save all the shared element names into a String array in onSaveInstanceState() like this:

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        sharedElementList?.run {
            outState.putStringArrayList(PENDING_EXIT_SHARED_ELEMENTS, ArrayList(this))
        }
    }
}

where const val PENDING_EXIT_SHARED_ELEMENTS = "android:pendingExitSharedElements" It's a constant defined in ActivityTransitionState

And to get the sharedElementList you can call this in onCreate()

setEnterSharedElementCallback(object : SharedElementCallback() {
        override fun onSharedElementsArrived(sharedElementNames: MutableList<String>?, sharedElements: MutableList<View>?, listener: OnSharedElementsReadyListener?) {
            super.onSharedElementsArrived(sharedElementNames, sharedElements, listener)
            sharedElementList = sharedElementNames?.toList()
        }

}

Next up the activity actually needs to be recreated for this to have effect - so only adding this will make it work if you rotate screen on Activity B.

Therefore I call recreate() on Activity B like 500-1000ms after I open the Activity C. That way the transition isn't laggy.

Just be cautious about calling supportPostponeEnterTransition() and startPostponedEnterTransition() because if they are calling them when entering Activity B, they will be called again after recreate()

In general it's enough to call the recreate once so I'm myself keeping a local flag in the Activity B for me to know if the Activity was already recreated or not yet, so that I don't do it unnecessarily too much every time I go from B to C and back.

Overall this is just a high level hacky solution and I was dealing with many more issues having recyclerviews in each Activity which makes things more complicated.

If you find any better please comment, I'd love to hear it but I can't spend any more time on this as two weeks of investigation of Android source code and comparing API28 and 29 has been enough for me :D

user1071762
  • 625
  • 1
  • 9
  • 14
0

That's because a behaviour change on Android 9: onStop is called after onSaveInstance, which causes the transitionNames not initialized if the Activity calls onStop before performing the return transition. You can refer to this page to learn more about this issue.

Anyway, in order to patch this glitch, you can add this line into your dependecies:

implementation 'io.github.xjunz:return-transition-patcher:+'

And call this method to patch all activities in the application.

// Call this to patch all activities. 
ReturnTransitionPatcher.patchAll(application)
xjunz
  • 31
  • 4