[Motion] Unloaded ImageView when returning from MaterialContainerTransform
See original GitHub issueDescription:
I’m using MaterialContainerTransform
to transition from Fragment A, to a Fragment B that contains a RecyclerView
whose items have ShapeableImageView
s. Note: Fragment A is part of a ViewPager2
, hosted by Fragment Z.
Transitionning from A to B works fine: transition is postponed until B’s RecyclerView
display is ready.
But when returning from B, we notice that images (that are loaded with Glide) are reset and blank.
Expected behavior:
Images loaded into ImageView
s should not be reset ; those should be preserved in the return transition.
Also, why is SheapeableImageView
showing black rounded corners ? This strange behavior of ShapeableImageView
is also noticeable on Android Studio’s layout preview (corners are then light grey).
Source code:
In Fragment Z:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
postponeEnterTransition(1000, TimeUnit.MILLISECONDS)
// Configure ViewPager adapter...
}
In Fragment A:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Some view initialization code [...]
viewModel.liveData.observe(viewLifecycleOwner) {
adapter.submitList(it)
val fragmentZ = requireParentFragment()
fragmentZ.requireView().parent?.doOnPreDraw {
fragmentZ.startPostponedEnterTransition()
}
}
}
private fun displayFragmentB() {
// Root item view from the clicked element in RecyclerView. Has transitionName set in onBindViewHolder
val itemView = ...
val sharedElementExtras = FragmentNavigatortExtras(itemView to "some_item_id")
requireParentFragment().apply {
exitTransition = Hold().apply {
duration = 300
addTarget(R.id.fragment_z)
}
// Reset transition set by other navigation events
reenterTransition = null
}
findNavController().navigate(R.id.to_fragment_b, sharedElementExtras)
}
In Fragment B:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
sharedElementEnterTransition = MaterialContainerTransform().apply {
drawingViewId = R.id.nav_host_fragment
duration = 300
scrimColor = Color.TRANSPARENT
setAllContainerColors(themeColorSurface)
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
postponeEnterTransition(500, TimeUnit.MILLISECONDS)
view.transitionName = "some_item_id"
viewModel.liveData.observe(viewLifecycleOwner) {
adapter.submitList(it)
view.parent?.doOnPreDraw {
startPostponedEnterTransition()
}
}
}
Android API version: 29 (Q)
Material Library version: 1.2.1
Device: Nokia 7.1, but also encountered on emulator.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:13 (2 by maintainers)
Top GitHub Comments
Thanks @mxalbert1996 and @hunterstich for your answers!
I just managed to make the return transition work for my use case. I’ve had to change the
Fragment
passed to Glide to its associatedActivity
(fragment.requireActivity()
) so that images are not cleared before being captured.There’s still a problem with
ShapeableImageView
’s corners, though. With a ShapeAppereance having 8dp rounded corners, black corners artifacts are visible during return transition. You can see those on the GIF I posted in the original post. This is less noticeable but still there.@thibseisel - thanks for the sample project.
I looked into this. The only workaround I was able to find is to use Glide’s
with
builder that accepts aContext
instead of aFragment
to keep Glide from registering with the Fragment’s lifecycle and clearing images when the Fragment is destroyed.So in the case of your sample, you would change
AlbumDetailFragment
s Glide call to:This works in my testing. Let me know how it goes for you.