Status Update
Comments
jb...@google.com <jb...@google.com> #2
I don't know if this is something that can be changed, but I'll look into it.
dn...@google.com <dn...@google.com> #3
Hmm... it is supposed to work like this, but you are seeing a bug.
jb...@google.com <jb...@google.com> #4
It cou8ld be tricky to get this right because the onAnimationEnd()
and onTransitionEnd()
often modify the state. We must execute the Runnable only after the state has been changed to its final value.
I think it could be dangerous to make a change, but it is possible to run all the internal listeners first, then run all of the external ones with the Runnable executed between. Again, it wouldn't be safe because we can't guarantee that only the internal listeners change the system state.
th...@outlook.com <th...@outlook.com> #5
Passing to Jeremy to get his thoughts
th...@outlook.com <th...@outlook.com> #6
What we really need is a signal to say when all transitions are done and with it running early, we don't have that. For fragments this means that we could end up moving the fragment to RESUMED
before all the transitions are actually completed and execute some code that is normally fine when the system is settled, but dangerous when it is not.
If moving onTransitionEnd()
might be too dangerous are there other options? If you are in the animateToStart
case should you even get an onTransitionEnd()
. Maybe all external listeners get is an onTransitionCancel()
since you are reversing a transition you started in the middle of it. Is that a safer signal to send back?
I think it is okay to separate the signals as long as they are explicit, but we for sure need a way to know that the Transition system is completely done doing any work and our Views are back in the original state that we passed them in.
il...@google.com <il...@google.com> #7
Maybe you could notify at the end of your animateToStart
lambda?
th...@outlook.com <th...@outlook.com> #8
Per offline discussion, we can move ahead with the solution suggested in
This will change the current order:
start transition > animateToStart > onTransitionEnd() > Runnable > finish up transition work
to
start transition > animateToStart > Runnable > finish up transition work > onTransitionEnd()
This has the implications that if developers are doing something with a specific result in their onTransitionEnd()
callback, they will also need to handle the cancellation case by overriding the new onTransitionEnd(Transition, boolean)
For example, if there is a transition from View_A
to View_B
and the onTransitionEnd()
callback has logic that expects View_B to be the final state, it will now need to add some additional logic based on the boolean in the case that View_A
is the final state.
jb...@google.com <jb...@google.com> #9
Branch: androidx-main
commit 889b310dee76183e0f89e76d014728f728190740
Author: George Mount <mount@google.com>
Date: Wed Dec 20 14:35:35 2023
Change order of listeners for seeking transitions.
Fixes: 307624554
When TransitionSeekController.animateToStart() is used,
externally added TransitionListeners will have onTransitionEnd()
called after the animateToStart()'s lambda. Internally-added
listeners will be called before the animateToStart()'s lambda.
Test: new test
Change-Id: Ic6a55916958f85d41c54d7739bde09cfc2352d7c
M transition/transition/src/androidTest/java/androidx/transition/SeekTransitionTest.kt
M transition/transition/src/main/java/androidx/transition/Transition.java
th...@outlook.com <th...@outlook.com> #10
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.transition:transition:1.5.0-alpha06
jb...@google.com <jb...@google.com>
il...@google.com <il...@google.com> #11
Thanks, we'll take another look.
jb...@google.com <jb...@google.com>
ap...@google.com <ap...@google.com> #12
Branch: androidx-main
commit 5fe62adfa9d530f4615a64d6f123a380beb61d9c
Author: Jeremy Woods <jbwoods@google.com>
Date: Wed Feb 21 22:47:46 2024
Fix issue with failing to cancel forward transitions
Prior to the Predictive back world, it was not possible to cancel any
transactions. They were atomic in nature and executing one meant that it
would finish. In the new world that is no longer the case, specifically
if you begin a forward transacation it is possible to start a predictive
back in the middle of that.
Currently, when you do this with Androidx Transitions, the view you are
seeking away from is immediately destroyed and if you do not complete
the back gesture, you are left with a blank screen.
What we should do instead is to immediately complete the forward
transaction, then begin the back gesture as if you had started from a
resumed fragment. This gets us into a known state that we can correctly
recover from.
RelNote: "Fixed an issue in Fragments where interrupting incoming
transitions with a Predictive back gesture would destroy the entering
view, potentially leaving a blank screen."
Test: Added FragmentTransitionSeekingTest
Bug: 319531491
Change-Id: Id3f228dd5f53742c68e6cb16b752022e18e00ec9
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
M transition/transition/src/androidTest/java/androidx/transition/FragmentTransitionSeekingTest.kt
M transition/transition/src/androidTest/java/androidx/transition/FragmentTransitionTest.kt
M transition/transition/src/main/java/androidx/transition/FragmentTransitionSupport.java
jb...@google.com <jb...@google.com> #13
This has been fixed internally and will be available in the Fragment 1.7.0-beta01
release.
th...@outlook.com <th...@outlook.com> #14
Thank you for your work.
Are the changes mentioned in
FATAL EXCEPTION: main
Process: com.example.pbfragmentsharedelement, PID: 3103
java.lang.IllegalStateException: setCurrentPlayTimeMillis() called after animation has been started
at androidx.transition.Transition$SeekController.setCurrentPlayTimeMillis(Transition.java:2778)
at androidx.transition.FragmentTransitionSupport.setCurrentPlayTime(FragmentTransitionSupport.java:265)
at androidx.fragment.app.DefaultSpecialEffectsController$TransitionEffect.onProgress(DefaultSpecialEffectsController.kt:798)
at androidx.fragment.app.SpecialEffectsController.processProgress(SpecialEffectsController.kt:441)
at androidx.fragment.app.FragmentManager$1.handleOnBackProgressed(FragmentManager.java:513)
at androidx.activity.OnBackPressedDispatcher.onBackProgressed(OnBackPressedDispatcher.kt:255)
at androidx.activity.OnBackPressedDispatcher.access$onBackProgressed(OnBackPressedDispatcher.kt:63)
at androidx.activity.OnBackPressedDispatcher$2.invoke(OnBackPressedDispatcher.kt:129)
at androidx.activity.OnBackPressedDispatcher$2.invoke(OnBackPressedDispatcher.kt:127)
at androidx.activity.OnBackPressedDispatcher$Api34Impl$createOnBackAnimationCallback$1.onBackProgressed(OnBackPressedDispatcher.kt:388)
at android.window.WindowOnBackInvokedDispatcher$OnBackInvokedCallbackWrapper.lambda$onBackStarted$0(WindowOnBackInvokedDispatcher.java:329)
at android.window.WindowOnBackInvokedDispatcher$OnBackInvokedCallbackWrapper$$ExternalSyntheticLambda5.onProgressUpdate(Unknown Source:2)
at android.window.BackProgressAnimator.updateProgressValue(BackProgressAnimator.java:161)
at android.window.BackProgressAnimator.-$$Nest$mupdateProgressValue(Unknown Source:0)
at android.window.BackProgressAnimator$1.setValue(BackProgressAnimator.java:61)
at android.window.BackProgressAnimator$1.setValue(BackProgressAnimator.java:57)
at com.android.internal.dynamicanimation.animation.DynamicAnimation.setPropertyValue(DynamicAnimation.java:731)
at com.android.internal.dynamicanimation.animation.DynamicAnimation.doAnimationFrame(DynamicAnimation.java:687)
at android.animation.AnimationHandler.doAnimationFrame(AnimationHandler.java:344)
at android.animation.AnimationHandler.-$$Nest$mdoAnimationFrame(Unknown Source:0)
at android.animation.AnimationHandler$1.doFrame(AnimationHandler.java:87)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1341)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1352)
at android.view.Choreographer.doCallbacks(Choreographer.java:952)
at android.view.Choreographer.doFrame(Choreographer.java:878)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1326)
at android.os.Handler.handleCallback(Handler.java:958)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8248)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
jb...@google.com <jb...@google.com> #15
If you used a snapshot from this morning it should be fixed. Are you doing the same thing in these 3 cases and seeing different results? Could you further explain how you get these 3 cases?
th...@outlook.com <th...@outlook.com> #16
I did use the very latest snapshot version from this morning.
There are 2 different ways to trigger an issue and both issues trigger the same leak from
The first issue, leading to the crash in the stacktrace in
Press the button to open the second fragment and interrupt the opening animation by performing the back gesture (without seeking).
Press the second fragment button again before the closing animation is finished and interrupt the opening animation again using the back gesture.
The second issue, to get into an undefined state, is to:
Press the button to open the second fragment.
Press the back button in the toolbar at the time the opening animation is finishing.
The timing has to be just right but the issue can be triggered fairly consistently.
Both issues can be experienced using the project attached to
jb...@google.com <jb...@google.com> #18
I am closing this as I have not been able to reliably produce any of the mentioned errors with the latest library versions and this bug was about providing support for shared elements, which did. I did see a case where if you use system back to interrupt, that the transition didn't finish, but I couldn't reproduce that either.
If you can provide an app that reproduces this case reliably please file a new bug.
th...@outlook.com <th...@outlook.com> #19
The last issue with predictive back I've come across was fixed in fragment-1.8.5. Thanks for the fixes.
Description
Component used: Fragment
After the release of Android 14 brought predictive back, Material Components added support for Material Motion Transitions . Unfortunately the shared element transition that would bring the coolest effects does not yet work, because the Fragment library does not support predictive back with this type of transition.
This is where I would like to request predictive back support for the shared element transition in the AndroidX Fragment library.
Ref:https://github.com/material-components/material-components-android/issues/3619#issuecomment-1883473193