material-components / material-components-android

Modular and customizable Material Design UI components for Android
Apache License 2.0
16.28k stars 3.06k forks source link

[Motion] Shared axis transition does not work when entering a fragment that contains a recycler view #1984

Open rickymohk opened 3 years ago

rickymohk commented 3 years ago

Description: When using shared axis transition going from a fragment to another fragment which contains a recycler view, the recycler view is not animated while the rest of the fragment is animated correctly. Going back has no issue, the recycler view get animated correctly when navigate up.

Expected behavior: The recycler view should be animated like other parts of the fragment

Source code: Follow the Transition between Fragments section in https://material.io/develop/android/theming/motion#shared-axis but use findNavController().navigate() instead of supportFragmentManager

Android API version: 30 Material Library version: 1.3.0-rc01 Device: CAT S41

To help us triage faster, please check to make sure you are using the latest version of the library.

We also happily accept pull requests.

rickymohk commented 3 years ago

I was using fragment-ktx:1.3.0-rc01. Saw this issue https://github.com/material-components/material-components-android/issues/1771#issue-713919953 and try to use fragment 1.2.5. This solves the issue when the destination contains ONLY the recycler view. But the issue still exists when the destination contains some more other views.

kdrag0n commented 3 years ago

I am also experiencing this issue with stable MDC and fragment 1.3.0. Demo video for clarification: https://streamable.com/h9m2cx

It's not that the recycler view is not animated at all, but the animation is incorrect. It appears to only animate the width, so the animation looks like it's stretching the view horizontally. ScrollView is also animated incorrectly: the scrollbar appears immediately without a transition and the content animation looks exaggerated.

ScrollView demo: https://streamable.com/rfawk6

A workaround for this bug is to set a solid background for the fragment:

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // Workaround for AndroidX bug: https://github.com/material-components/material-components-android/issues/1984
        view.setBackgroundResource(R.drawable.solid_background)
    }

res/drawable/solid_background.xml:

<?xml version="1.0" encoding="utf-8"?>
<color xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?android:attr/colorBackground" />

I'm not sure why this helps — maybe because it forces the fragment's view to occupy all the space in the container immediately instead of waiting for the recycler view to be initialized — but it gets the job done.

Correct behavior with the workaround: RecyclerView and ScrollView

solrudev commented 2 years ago

A workaround for this bug is to set a solid background for the fragment

On API level < 21 this solution will crash, and also while editing the drawable there will be a warning: "Using theme references in XML drawables requires API level 21".

So in order to make it work with lower APIs instead of creating a drawable I did the following:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    val colorBackground = MaterialColors.getColor(view, android.R.attr.colorBackground)
    view.setBackgroundColor(colorBackground)
}