I have a MainActivity
with the following layout :
<androidx.fragment.app.FragmentContainerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_host_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph_main"/>
The rest are in the Fragments.
I have two Fragments where I animate the transition with shared elements such as a list fragment and a detail fragment.
I am using the Navigation Component
from JetPack with the SafeArgs
plugin alongside with transitions classes from the AndroidX
package.
val directions = AlbumsListFragmentDirections.actionAlbumsListFragmentToAlbumDetailsFragment(
ViewCompat.getTransitionName(binding.imageThumbnail)!!
)
val extras = FragmentNavigatorExtras(
binding.imageThumbnail to ViewCompat.getTransitionName(binding.imageThumbnail)!!
)
findNavController().navigate(directions, extras)
I am also using postponeEnterTransition()
and startPostponedEnterTransition()
to trigger transitions animations when UI is ready to do so.
On any L+ devices, as Shared Elements Transitions are native components from the OS, there are no issue.
However, on my KitKat device (Samsung S4), since my min API is 19, the app crashes when calling the above code snippet with these crash logs:
java.lang.IllegalStateException: Views added to a FragmentContainerView must be associated with a Fragment. View androidx.transition.GhostViewApi14{42a33b30 V.ED.... ......ID 0,0-0,0} is not associated with a Fragment.
at androidx.fragment.app.FragmentContainerView.addView(FragmentContainerView.java:276)
at android.view.ViewGroup.addView(ViewGroup.java:3557)
at android.view.ViewGroup.addView(ViewGroup.java:3533)
at androidx.transition.GhostViewApi14.addGhost(GhostViewApi14.java:53)
at androidx.transition.GhostViewUtils.addGhost(GhostViewUtils.java:30)
at androidx.transition.ChangeTransform.createGhostView(ChangeTransform.java:391)
at androidx.transition.ChangeTransform.createAnimator(ChangeTransform.java:272)
at androidx.transition.Transition.createAnimators(Transition.java:744)
at androidx.transition.TransitionSet.createAnimators(TransitionSet.java:470)
at androidx.transition.TransitionSet.createAnimators(TransitionSet.java:470)
at androidx.transition.TransitionSet.createAnimators(TransitionSet.java:470)
at androidx.transition.Transition.playTransition(Transition.java:1821)
at androidx.transition.TransitionManager$MultiListener.onPreDraw(TransitionManager.java:300)
at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:879)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2131)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1236)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6471)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:803)
at android.view.Choreographer.doCallbacks(Choreographer.java:603)
at android.view.Choreographer.doFrame(Choreographer.java:573)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:789)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
The error is simple to understand: FragmentContainerView
does not support any views that are not associated with a Fragment. And apparently, there's a androidx.transition.GhostViewApi14
at the root of this crash.
Looking into the source code of this class, I learned it's a backport for a native view added in L to support transitions I believe.
I attempted to fix that issue by reverting back to the old way, in XML file for my MainActivity
declared in land-v19
:
<fragment
android:name="androidx.navigation.fragment.NavHostFragment"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_host_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph_main"/>
However, the app still crashes on my KitKat device.
Is it possible the framework (maybeAppCompat
- I'm using stable version 1.1.0
with activity-ktx-1.1.0'
?) automatically replaces <fragment>
by a FragmentContainerView
?
It appears so, because I removed that XML layout, and pasted its content in the original one. Simply put, all versions will use that XML with <fragment>
Is that a bug ? If so, should it be reported or is it known ? Or am I doing something wrong ?
Thanks for the help !