Status Update
Comments
il...@google.com <il...@google.com>
ap...@google.com <ap...@google.com> #2
Jeremy, is this still an issue? I think the problem was that you had two transitions targeting the same View for the same action (e.g. two Slide() transitions).
ap...@google.com <ap...@google.com> #3
I have a similar issue with plain AnimatorSet:
set.start()
set.pause()
set.setCurrentPlayTime(100)
set.setCurrentPlayTime(0)
set.setCurrentPlayTime(100)
set.resume()
doesn't play animation in resume().
ap...@google.com <ap...@google.com> #4
Should clarify that if I filter out setCurrentPlayTime(0)
(or replace it with setCurrentPlayTime(1)
) it works well.
Also even with setCurrentPlayTime(0)
, onAnimationEnd
is notified with correct delay (as if the animation has played).
ap...@google.com <ap...@google.com> #5
@
I think that is intended for Animator. If you set the currentPlayTime
to 0 or the total duration the animator completes. We do some
ap...@google.com <ap...@google.com> #6
Did some investigation on the Fragment side and it seems like the merged transition is targeting correctly.
Exiting Transition: Slide@aa9288e: tgts(android.widget.LinearLayout{f9add3d})
>>>>> ExitingViews <<<<<
View: android.widget.LinearLayout{f9add3d}
Entering Transition: Slide@35b8af: tgts(android.widget.LinearLayout{b7f24bc})
>>>>> EnteringViews <<<<<
View: android.widget.LinearLayout{b7f24bc}
Final merged transition: TransitionSet@7bc1c45:
TransitionSet@e133f9a:
Slide@aa9288e: tgts(android.widget.LinearLayout{f9add3d})
Slide@35b8af: tgts(android.widget.LinearLayout{b7f24bc})
merged transition passed to controlDelayedTransition: TransitionSet@7bc1c45:
TransitionSet@e133f9a:
Slide@aa9288e: tgts(android.widget.LinearLayout{f9add3d})
Slide@35b8af: tgts(android.widget.LinearLayout{b7f24bc})
Still digging.
ap...@google.com <ap...@google.com> #7
Branch: androidx-main
commit 567b7459329d1ec8d27a8c6fe1c4a86442065d7d
Author: Jeremy Woods <jbwoods@google.com>
Date: Tue Sep 26 20:06:54 2023
Add additional logging for transitions
Adding more debug logging in transitions to track the entering and
exiting transitions as well as the final merged transition and its
targets.
Test: added logging
Bug: 300157785
Change-Id: I0d9ad72b865422493c6c895ddb6115abf85eed16
M fragment/fragment/src/main/java/androidx/fragment/app/DefaultSpecialEffectsController.kt
ap...@google.com <ap...@google.com> #8
So I have isolated this outside of fragment into something much simpler and I think it breaks down when it comes to the adding and removing of Views with animateToStart.
The attached sample is a simple add that goes between two screens BLUE
and GREEN
. It has code for both the 1.5.0-alpha03
and 1.5.0-alpha04
versions, but I think alpha04 is currently broken in another way so I will upload the alpha03 version here.
This is integrated with predictive back similar to how fragment is, so upon cancelling we call animateToStart
, then we do a beginDelayedTransition
on a 0
duration Fade()
and we reverse the view visibility back to what it was prior to starting the transition.
If you only do visibility, cancel always works the view never goes away, it is wonderful, but when you do adding and removing views like we need to in fragment it fails.
First the code for beginDelayedTransition goes from this:
TransitionManager.beginDelayedTransition(container, Fade().apply {
duration = 0
})
reverseViews()
to this:
TransitionManager.beginDelayedTransition(container, Fade().apply {
duration = 0
addListener(onEnd = {
reverseViews()
blueScreen.visibility = View.VISIBLE
greenScreen.visibility = View.VISIBLE
})
})
reverseViews(useVisibility = true)
We need to make this change because after the animateToStart()
view is still parented by the overlay, so we call reverseViews(useVisibility = true)
to only change the visibility and then once the transition finishes we can call reverseViews()
to parent the view properly, then we make both views visible again.
From our perspective after the 0
duration transition our views are back in the proper state, but they do not transition properly after a cancel.
If the app is doing this wrong and we can make the appropriate fixes, doing the same in fragment should resolve this. There is logging available that shows the state of the views when we start the transition.
jb...@google.com <jb...@google.com>
il...@google.com <il...@google.com>
ap...@google.com <ap...@google.com> #9
The API has changed since that project was created in a way that makes the API more robust. I'm hoping that has fixed this...
ap...@google.com <ap...@google.com> #10
There appears to be a problem with the order of operations. I'm going to look into fixing that.
ap...@google.com <ap...@google.com> #11
Branch: androidx-main
commit e57dd5f9ac6cbb8cf83b221e2d5b3fbd3e88ce6b
Author: George Mount <mount@google.com>
Date: Thu Nov 09 14:33:53 2023
Fix animateToStart with Slide.
Fixes: 300157785
Slide was not repositioning the View to its proper
translation after animating it to the start position.
This fixes that so that it is moved.
Test: new test
Change-Id: I698f4dbcef46304f9aa545847d205f7b70c80d63
M transition/transition/src/androidTest/java/androidx/transition/SlideEdgeTest.java
M transition/transition/src/androidTest/java/androidx/transition/TranslationAnimationCreatorTest.java
M transition/transition/src/main/java/androidx/transition/TranslationAnimationCreator.java
ap...@google.com <ap...@google.com> #12
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.transition:transition:1.5.0-alpha05
ap...@google.com <ap...@google.com> #13
Branch: androidx-main
commit 8a019327ad267d6251167e400ea79cb8a54243b3
Author: Ian Lake <ilake@google.com>
Date: Fri Jun 24 20:53:15 2022
Move childFragmentManager state out of savedInstanceState
Migrate the childFragmentManager state out of the same
Bundle as is passed to onSaveInstanceState(). Instead,
store that Bundle as a separate value in the Fragment's
saved state Bundle.
Test: existing tests pass
BUG: 207158202
Change-Id: I456259053dfc833d39c4f648e23735b98cb65714
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentStateManager.java
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
M fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java
ap...@google.com <ap...@google.com> #14
Branch: androidx-main
commit 3ccf9b6e609c6f2130689bb2f8c4bff6e2907df3
Author: Ian Lake <ilake@google.com>
Date: Fri Jun 24 21:38:19 2022
Use all initial state when saving an initializing fragment
With the state split across multiple fields, saving the
state of an Fragment still in the INITIALIZING state should
use the entire saved state Bundle set by
setInitialSavedState() rather than only extracting the
onSaveInstanceState() bundle out of it.
Test: existing tests pass
BUG: 207158202
Change-Id: I95868473b28b179d7cc0b0e606427928982dc96c
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentStateManager.java
ap...@google.com <ap...@google.com> #15
Branch: androidx-main
commit f7ec0cc1786b4a16c0569cc07ecf5093693bcab0
Author: Ian Lake <ilake@google.com>
Date: Fri Jun 24 21:30:15 2022
Skip empty/null keys when saving Fragment state
Each key in the Fragment's saved state Bundle takes up
space in the limited resource that is the total
saved instance state. By removing empty or null keys,
we can ensure that the set of saved key/values is
minimized.
Test: existing tests pass
BUG: 207158202
Change-Id: I4e0f4772982406bfe10e64d78d26e93f4e2bc387
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentStateManager.java
ap...@google.com <ap...@google.com> #16
Branch: androidx-main
commit 5cc7478b61c2f48452770285d7ba8c74be907b19
Author: Ian Lake <ilake@google.com>
Date: Fri Jun 24 21:18:57 2022
Move SavedStateRegistry state out of savedInstanceState
Migrate the SavedStateRegistry's state out of the same
Bundle as is passed to onSaveInstanceState(). Instead,
store that Bundle as a separate value in the Fragment's
saved state Bundle.
Test: existing tests pass
BUG: 207158202
Change-Id: I903d56901e6c5a5caf2890a4dbe5471c73169b56
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentStateManager.java
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
M fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java
ap...@google.com <ap...@google.com> #17
Branch: androidx-main
commit 28e7a78343af524c7854a3f951809448a8457dd1
Author: Ian Lake <ilake@google.com>
Date: Fri Jun 24 21:58:43 2022
Move and rename _TAG constants to _KEY
Rename all constants used as Bundle keys to use
the _KEY suffix rather than _TAG to prevent mistaking
them for debug tags.
Also moves all keys associated with the Fragment's state
into FragmentStateManager, which is responsible for
saving the Fragment's state. Keys associated with saving
the FragmentManager's state are still in FragmentManager.
Test: existing tests pass
BUG: 207158202
Change-Id: I6e47a4a0ec84c708f9a3c984e737ed7314530156
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentStateManager.java
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
M fragment/fragment/src/main/java/androidx/fragment/app/BackStackState.java
M fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java
M fragment/fragment/src/androidTest/java/androidx/fragment/app/BackStackStateTest.kt
il...@google.com <il...@google.com> #18
The saved state of Fragments has been split entirely between private library state (custom Parcelable
classes) and state provided by you, the developer, which is now always stored in a Bundle
that allows determining exactly which part of the fragment's state is too large.
The final structure is as follows:
In the Activity's onSaveInstanceState
, the "android:support:fragments"
key now contains a Bundle that contains the following information:
"state"
- the privateParcelable
storing theFragmentManager
's saved state (e.g., the fragment back stack info)- For each
that has been set viaFragment Result setFragmentResult
but has not yet been delivered:"result_$name"
-> (user defined Bundle) - For each Fragment (where the
fragment_id
matches the UUIDs found in the ):debug logging "fragment_$fragment_id"
-> Bundle"state"
-> the privateParcelable
storing theFragment
's saved state (e.g., the class name, max lifecycle, etc.)"arguments"
-> (Bundle of arguments)"savedInstanceState"
-> (onSaveInstanceState
filled Bundle)"registryState"
-> (SavedStateRegistry
filled Bundle)"childFragmentManager"
-> The “android:support:fragments” equivalent Bundle of the childFragmentManager
, which would lead us recursively down the tree"viewState"
-> theSparseArray<Parcelable>
returned byView.saveHierarchyState
representing theFragment View state "viewRegistryState"
-> (ViewSavedStateRegistry
filled Bundle)
This will be fully available in Fragment 1.6.0-alpha01.
Description
Component used: Fragment
Version used: 1.4.0
There are tools like toolargetool that let you explore what is taking up space in your saved instance state. However, it has no visibility into custom Parcelables like the
FragmentManagerState
used to store the entire FragmentManager's hierarchy of saved state.This makes it hard to differentiate between the state of the FragmentManager itself and the state of each individual fragment, and, within a particular fragment, differentiating the view state, arguments, state provided by
onSaveInstanceState()
, and the fragment'sSavedStateRegistry
.Therefore the focus should be on exposing the hierarchy of fragments - the bookkeeping associated with an individual Fragment and the FragmentManager specific state can and should remain as separate Parcelable instances that don't expose their internal fields.