question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Motion] Unloaded ImageView when returning from MaterialContainerTransform

See original GitHub issue

Description: I’m using MaterialContainerTransform to transition from Fragment A, to a Fragment B that contains a RecyclerView whose items have ShapeableImageViews. 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.

material_container_bug

Expected behavior: Images loaded into ImageViews 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:open
  • Created 3 years ago
  • Reactions:1
  • Comments:13 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
thibseiselcommented, Dec 2, 2020

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 associated Activity (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.

1reaction
hunterstichcommented, Dec 2, 2020

@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 a Context instead of a Fragment 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 AlbumDetailFragments Glide call to:

            Glide.with(requireContext()).asBitmap()
                .load(it.artworkUrl)
                .into(album_art_view)

This works in my testing. Let me know how it goes for you.

Read more comments on GitHub >

github_iconTop Results From Across the Web

MaterialContainerTransform transition is not Working on Return
I dynamically set the ImageView transitionName in each RecyclerView item, and pass that to the destination Fragment which then copies the ...
Read more >
How to Use Material Container Transform with RecyclerView + ...
Open Android Studio. Create new project with “Empty Activity” option. 2. First, we need to setup Navigation component. For convenience, we are also...
Read more >
Motion - Material Design
MaterialContainerTransform internally configures the transition's properties based on whether or not it's entering or returning. If you need to customize ...
Read more >
TextInputLayout | Android Developers
Returns whether any hint state changes, due to being focused or non-empty text, are animated. boolean, isHintEnabled(). Returns whether the ...
Read more >
Shared Element using MaterialContainerTransform in Android
The Material motion system for Android is a set of transition ... are no mapping views for shared element to create a returning...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found