Status Update
Comments
ba...@gmail.com <ba...@gmail.com> #2
This happens when fragments use animation whereby it doesn't wait for animations to complete and moves directly to RESUMED state.
The entry's listener to Fragment state does not get attached because it was attaching only if Fragment was in CREATED / STARTED state.
yc...@gmail.com <yc...@gmail.com> #3
Branch: androidx-main
commit 16afaea63fc18ca7cc298e6650e0463083ba8ad7
Author: Clara Fok <clarafok@google.com>
Date: Mon Feb 27 17:27:15 2023
Fix FragmentNavigator resume states
Entries previously were not attaching fragment lifecycle observers because it would do so only if Fragment was STARTED or CREATED. But when using animations, Fragments would jump straight to RESUME and no observers would be attached.
Observers are now attached as long as Fragment is atleast STARTED. Since initial entry is not added to backStack, we store its entry to later attach an observer when its fragment is attached.
This CL also lays the foundation for attaching observers upon configuration changes / recreates.
Test: ./gradlew navigation:navigation-fragment:cC
Bug: 269646882
Relnote: "Fixes regression in navigation 2.6.0-alpha06 where NavBackStackEntry is not moved to RESUMED state"
Change-Id: Ib35896636c187da5bd11ea06234a3ea815fdeb68
M navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt
A navigation/navigation-fragment/src/androidTest/res/anim/fade_enter.xml
A navigation/navigation-fragment/src/androidTest/res/anim/fade_exit.xml
M navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/FragmentNavigator.kt
ri...@gmail.com <ri...@gmail.com> #4
This has been fixed internally and will be available in navigation 2.6.0-alpha07
yu...@gmail.com <yu...@gmail.com> #5
Branch: androidx-main
commit c73552953192ba60a879f5e51218f6e157a24beb
Author: Clara Fok <clarafok@google.com>
Date: Tue Feb 28 14:47:30 2023
Add FragmentNavigator test
Ensure initial fragments and their entries are correctly replaced and destroyed when navigate and popping consecutively
Test: ./gradlew navigation:navigation-fragment:cC
Bug: 269646882
Change-Id: I552ddd3d74f20612c4c91336eb4af9e6aa99c146
M navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt
M navigation/navigation-fragment/src/androidTest/res/navigation/nav_simple.xml
st...@detroitlabs.com <st...@detroitlabs.com> #6
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.navigation:navigation-fragment:2.6.0-alpha07
na...@gmail.com <na...@gmail.com> #7
NavBackStackEntry is still not triggering RESUMED on androidx.navigation:navigation-fragment:2.6.0-alpha09
in certain cases, where after a locale or uiMode change with
AppCompatDelegate.setApplicationLocales
AppCompatDelegate.setDefaultNightMode
Issue can be reproduced with attaching LifecycleObserver to the currentBackStackEntry of a Home fragment like so:
findNavController().currentBackStackEntry?.lifecycle?.let {
if (it.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
Timber.d(Constants.LOG_INFO, "lifecycle.currentState", "resumed")
} else {
val testLifecycleObserver = object : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
Timber.d(Constants.LOG_INFO, "lifecycle.currentState", "onResumed")
it.removeObserver(this)
}
}
it.addObserver(testLifecycleObserver)
}
}
After performing a config change as mentioned above on a Settings fragment, upon performing a popBackStack/navigateUp to Home fragment, the DefaultLifecycleObserver's onResume will not be triggered. Issue does not occur if a config change is not performed.
ri...@gmail.com <ri...@gmail.com> #8
I believe this was actually addressed as part of the Navigation
sk...@gmail.com <sk...@gmail.com> #9
sk...@gmail.com <sk...@gmail.com> #10
dn...@google.com <dn...@google.com> #11
Note: Please upload the files to google drive and share the folder to android-bugreport@google.com, then share the link here.
st...@gmail.com <st...@gmail.com> #13
dn...@google.com <dn...@google.com> #14
st...@gmail.com <st...@gmail.com> #15
gk...@gmail.com <gk...@gmail.com> #16
m4...@gmail.com <m4...@gmail.com> #17
dg...@gmail.com <dg...@gmail.com> #18
Should we use one of the workarounds posted here?
il...@google.com <il...@google.com> #19
While we can't fix the general case here within an unbundled library like Fragments, we can fix this in cases where the parent layout is a FrameLayout / extends FrameLayout by delaying the removal of the old View until after the animation completes under the assuption that children of a FrameLayout are suitably independent that animating one in while the other still exists in the layout is not an issue.
This should at least fix the issue for libraries built on top of Fragments such as Navigation.
[Deleted User] <[Deleted User]> #21
dc...@gmail.com <dc...@gmail.com> #22
ga...@gmail.com <ga...@gmail.com> #23
Ignore the fact that this library is a React Native library, it works the same for native apps.
ki...@gmail.com <ki...@gmail.com> #24
I've made a custom view group based on ScreenCoordinatorLayout
In bug case, Fragment.animateRemoveFragment() is called, but
ja...@planticle.com.au <ja...@planticle.com.au> #25
Still, this is was a frustrating and time consuming bug to work around, and I look forward to seeing a fix for this in the Jetpack Navigation library.
mi...@gmail.com <mi...@gmail.com> #26
We probably need to stick to activities if we want to follow material design guidelines.
I also look forward for this being fixed.
mi...@gmail.com <mi...@gmail.com> #27
mi...@gmail.com <mi...@gmail.com> #28
With the Navigation Component, and because of this limitation, is impossible to have an "slide on top" kind of transition.
ni...@webwag.com <ni...@webwag.com> #29
Currently, it's a FrameLayout which has this issue.
From NavHostFragment.java :
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
FrameLayout frameLayout = new FrameLayout(inflater.getContext());
// When added via XML, this has no effect (since this FrameLayout is given the ID
// automatically), but this ensures that the View exists as part of this Fragment's View
// hierarchy in cases where the NavHostFragment is added programmatically as is required
// for child fragment transactions
frameLayout.setId(getId());
return frameLayout;
}
je...@gmail.com <je...@gmail.com> #30
pe...@gmail.com <pe...@gmail.com> #31
Here may be a solution:
jb...@google.com <jb...@google.com>
ap...@google.com <ap...@google.com> #32
Branch: androidx-master-dev
commit 2534c731cc31a615e4584d74327521ec8c5a8aa7
Author: jbwoods <jbwoods@google.com>
Date: Thu Jun 20 12:42:37 2019
Draw exit animations first in FragmentContainerView
ViewGroups always draw exiting view animations last. For Fragments, this
means that the exiting Fragment is always on top of all others. There
can be no interaction with entering fragments, and there is the
possiblity of a "pop" when the exit animation finishes to reveal the
Fragment underneath.
FragmentContainerView overrides the dispatchDraw and drawChild method to
force all disappearing children to be drawn first. It overrides public
methods from ViewGroup to build the proper list of transitioning views
and disappearing child views.
Test: Added units tests, tested visually in app, ./gradlew checkApi
BUG: 37036000
Change-Id: I054eaf4ae234258bc7abec22c4c8e559a2c6be71
M fragment/fragment/api/1.2.0-alpha01.txt
M fragment/fragment/api/current.txt
M fragment/fragment/api/restricted_1.2.0-alpha01.txt
M fragment/fragment/api/restricted_current.txt
M fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentContainerViewTest.kt
M fragment/fragment/src/androidTest/res/layout/fragment_container_view.xml
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentContainerView.java
ge...@gmail.com <ge...@gmail.com> #33
[Deleted User] <[Deleted User]> #34
1. When going forward, I want exit animation to be bottom, and enter animation on top
2. When going backwards, I want exit animation on top, and enter animation on the bottom.
That way I could replicate iOS animation behavior where new fragment "comes on top" on previous, but when click back, I also want that fragment to disappear "from the top" and reveal previous fragment beneath it. android:zAdjustment sounds like something that should fix this problem, but is it working for Fragments and Navigation library?
Can anybody help me here?
il...@google.com <il...@google.com> #35
il...@google.com <il...@google.com>
bi...@gmail.com <bi...@gmail.com> #36
or...@gmail.com <or...@gmail.com> #37
"Fragments using exit animations are drawn before all others for FragmentContainerView. This ensures that exiting Fragments do not appear on top of the view."
Is our long national nightmare of improperly drawn transition animations over?
mo...@gmail.com <mo...@gmail.com> #38
^ This. I think ideally we should have a way of telling the Fragment its Z ordering during the animation. I know that are ways, but couldn't find any that works with the Navigation Components.
ma...@gmail.com <ma...@gmail.com> #39
I am experiencing the same issue for version 1.2.3 when using the "FragmentContainerView" and setting "EnterTransition" to a slide transition, and using an exisiting fade transition in "ExitTransition"?
So I am not using "FragmentTransaction.setCustomAnimations", but I guess it is supposed to work the same way?
[Deleted User] <[Deleted User]> #40
- works with setCustomAninations
- still does not work with setExitTransition / setEnterTransition
It looks like FragmentContainerView.startViewTransition is not called properly in the broken case, which causes that FragmentContainerView falls into the standard drawing path.
[Deleted User] <[Deleted User]> #41
The actual problem with setExitTransition / setEnterTransition is caused by fact that any subclass of Visibility transition (e.g. Fade, Slide, etc.), uses ViewOverlay to realize the animation when the exiting View is removed from its parent. And this is actually happening when performing replace() Fragment transaction. The trouble is than the entering view wont use ViewOverlay and will be effectively BELOW the exiting view :(
It is very sad that such basic usecases are still broken :(
I really cant believe that it was not catched earlier :(
As a workaround, one may try to write customized FragmentContainerVIew (cant inherit, because the one from Jetpack is final.... ) and write a customized set of Transitions that does not use ViewOverlay or use it in consistent manner preserving the z-order.
gc...@neptuneretailsolutions.com <gc...@neptuneretailsolutions.com> #42
Problem not fixed for Translations - suggest reopening.
My fix to allow enterTransition to act as if Hold() was working correctly. I don't enterTransition animate at all:
exitTransition = HoldBackground(resources).setDuration(duration)
enterTransition = Slide(Gravity.RIGHT).setDuration(duration)
With HoldBackground looking like this:
class HoldBackground(val resources : Resources) : Transition() {
init {
duration = resources.getInteger(android.R.integer.config_mediumAnimTime).toLong()
}
var inProgress = false
@Synchronized
override fun captureStartValues(transitionValues: TransitionValues) {
if(inProgress) return
transitionValues.view.also { exitingView ->
exitingView.parent.also { fragmentContainer ->
if(fragmentContainer is View && exitingView.width > 0 && exitingView.height > 0) {
inProgress = true
val previousBackground = fragmentContainer.background
val bitmap = Bitmap.createBitmap(
exitingView.width,
exitingView.height,
Bitmap.Config.ARGB_8888
)
exitingView.draw(Canvas(bitmap))
fragmentContainer.background = BitmapDrawable(resources, bitmap)
// Simple animator so timing matches developer animation scales
val animator = ValueAnimator.ofInt(0, 1).setDuration(duration)
animator.addListener(object : BlankAnimatorListener() {
override fun onAnimationEnd(animation: Animator?) {
fragmentContainer.background = previousBackground
inProgress = false
}
})
animator.start()
}
}
}
}
override fun captureEndValues(transitionValues: TransitionValues) {}
}
It's very likely stupidly resource intensive given it's creating a screen size bitmap... but it does happen to work.
yo...@gmail.com <yo...@gmail.com> #43
- Cancelling replace-fragment transitions, i.e. navigating up during a transition, causes the pop-exiting fragment to appear below the pop-entering fragment.
- It doesn't work with setExitTransition / setEnterTransition. Entering fragment is below the exiting fragment.
I have no words for this. Ill probably just use multiple-activities (instead of single-activity) and use activity transitions.
If someone has a solution, it will be much appreciated.
Description
ft.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left);
slide_in_right.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="
android:shareInterpolator="true"
android:interpolator="@android:anim/decelerate_interpolator">
<translate android:fromXDelta="100%"
android:toXDelta="0%" android:fromYDelta="0%"
android:toYDelta="0%" android:duration="400">
</translate>
</set>
anim.slide_out_left.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="
android:shareInterpolator="true"
android:interpolator="@android:anim/decelerate_interpolator"
android:zAdjustment="bottom">
<translate android:fromXDelta="0%"
android:toXDelta="-50%" android:fromYDelta="0%"<!-- -50% shows the problem, 100% does not -->
android:toYDelta="0%" android:duration="400">
</translate>
</set>
(The zAdjustment tag does nothing)
The exiting fragment will be on top of the entering fragment, which is the opposite behavior than what is expected or useful. Currently, an exiting fragment must leave the frame completely, otherwise it will be on top of the entering fragment at the end of the animation, at which point in the last frame of the animation the exiting fragment will pop out of existence. The Z order of the fragments should be reversed or made customizable. The current z ordering offers no advantages.
I am trying to achieve the material effect of putting one "page" of a fragment on top of another while moving the exiting "page" somewhat to the left (50%), rather than 100% which would give the effect of just shoving the exiting "page" to the left, not putting it under the entering fragment. There are some work arounds described here
but they don't apply to my case.