Status Update
Comments
jb...@google.com <jb...@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).
ka...@droidsonroids.pl <ka...@droidsonroids.pl> #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().
il...@google.com <il...@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).
ma...@marcardar.com <ma...@marcardar.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
il...@google.com <il...@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.
ha...@gmail.com <ha...@gmail.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
il...@google.com <il...@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.
w....@futuremind.com <w....@futuremind.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...
hu...@gmail.com <hu...@gmail.com> #10
There appears to be a problem with the order of operations. I'm going to look into fixing that.
ka...@live.com <ka...@live.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
hu...@gmail.com <hu...@gmail.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
ka...@live.com <ka...@live.com> #13
It's not only about performance. Using FragmentContainerView
is breaking the app.
Check the title. When you use FragmentContainerView
findNavController()
is not working anymore!
hu...@gmail.com <hu...@gmail.com> #14
Yeah sorry for confusion, I should have been clearer.
I mean I understand that it breaks the app if we address the warning. And what I wanted to say was even if it didn't break the app, I don't think it's a valid warning since using replacing <fragment> with
FragmentContainerView` would create extra nested layout while there is no benefit gained.
il...@google.com <il...@google.com> #15
Re #10 - yes, you should always use FragmentContainerView
. There are absolutely other fixes around window insets and layout issues that occur when a fragment's root layout is directly within other layouts such as ConstraintLayout
, besides the underlying issues with the <fragment>
tag where fragments added via that tag go through lifecycle states entirely differently from the other Fragments added to the FragmentManager
. The Lint check is there exactly because you absolutely should switch over to FragmentContainerView
in all cases. It is not a no-op or negative even for a single static fragment.
FragmentContainerView
uses a FragmentTransaction
to add the initial fragment. If you were to use that approach manually, you'd note that findNavController()
would not work in that case either. The whole point of FragmentContainerView
is to provide a consistent path and lifecycle transition points for all fragments - as mentioned in onCreate()
is not where you should be accessing the Fragment's views, which is why getting the NavController
from the NavHostFragment
itself is the recommended solution in
ka...@live.com <ka...@live.com> #16
Re #15 - that can be all well and true, however in the state it's now it's pure madness.
Look at this stack overflow question <fragment>
and I guarantee you most developers won't think twice about it. At the and all the good intensions are useless.
So until there is a lint check for findNavController()
in onCreate()
telling developer to call it later (in onPostCreate
) or at least documentation stating this fact, you can't expect people will actually switch to FragmentContainerView
.
Another option would be apply suggestion from #5 and incorporate searching fragment manager in findNavController
before throwing exception that NavController
is not present.
Long story short, as it is right now is bad and you shouldn't be turning a blind eye to it.
hu...@gmail.com <hu...@gmail.com> #17
Re #15 - thanks for the clarification. I wasn't aware of the issue with using <fragment>
in xml. Is it documented somewhere or is there any related bug report?
While I generally agree with #16, I think the original issue was the default generated code in Android Studio uses <fragment>
in XML and also having findNavController
in onCreate()
. If it could be updated by Android team to properly use FragmentContainerView
(for example can use what's recommended in #4), a lot of confusion can be avoided. At the end of the day, Android Studio's example code should reflect the most correct and recommended way of doing things.
ro...@gmail.com <ro...@gmail.com> #18
I'll stick to #4.
RG
ru...@gmail.com <ru...@gmail.com> #19
working in onCreate()
val navHostFragment by lazy { supportFragmentManager.findFragmentById(R.id.navHostFragment) as NavHostFragment }
val navController get() = navHostFragment.navController
override fun onCreate(savedInstanceState: Bundle?) {
navHostFragment.childFragmentManager...
}
lu...@lloydsbanking.com <lu...@lloydsbanking.com> #20
I'm curious about the use cases that lead to this exception. If the user has defined the nav graph and set it as the nav graph of the FragmentContainerView
, what other functionality do they require during onCreate()
?
ka...@droidsonroids.pl <ka...@droidsonroids.pl> #21
Ad #20 for example one may want to parametrize start destination depending on some condition.
da...@gmail.com <da...@gmail.com> #22
ma...@americium.org <ma...@americium.org> #23
For an activity, onPostCreate works. For example in the activity:
override fun onPostCreate(savedInstanceState: Bundle?) {
super.onPostCreate(savedInstanceState)
// Needs to be in the post create
// Refer issue https://issuetracker.google.com/issues/142847973
_binding.navHostFragment.findNavController().addOnDestinationChangedListener { _, destination, _ ->
// code goes here :)
}
}
}
mo...@gmail.com <mo...@gmail.com> #25
This is the updated answer.
[Deleted User] <[Deleted User]> #26
sp...@gmail.com <sp...@gmail.com> #27
Just ran into this today and I am sad that this is marked as "infeasible" when a good response to this problem, at minimum, is to update the boilerplate code for new projects so that it doesn't generate code that automatically gets complaints from lint and then auto-fixes to broken code.
na...@gmail.com <na...@gmail.com> #28
this seems working but handler is deprecated is showing
ps: Im using nav-frag 2.7+ and viewbinding so first method is also not working
Description
Version used: 1.2.0-beta02
Devices/Android versions reproduced on: all
When the NavHostFragment is inflated using FragmentContainerView, if you attempt to use findNavController in the onCreate() of the Activity, the nav controller cannot be found. This is because when the fragment is inflated in the constructor of FragmentContainerView, the fragmentManager is in the INITIALIZING state, and therefore the added fragment only goes up to initializing. For the nav controller to be properly set, the fragment view needs to be created and onViewCreated() needs to be dispatched, which does not happen until the ACTIVITY_CREATED state.
We should either force the fragment to create a view right after being added to the FragmentManager, or find a way to wait for the FragmentManager to reach a higher state before allowing the Navigation onCreate to be called.
The following options can be used as viable work arounds:
1. Retrieve the navController directly from the NavHostFragment.
val navHostFragment = supportFragmentManager.findFragmentById(R.id.my_nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController
2. Post the call to the findNavController method on a handler and execute all actions that need it after that post is complete.
3. Continue to use the fragment tag (<fragment>) to inflate the NavHostFragment