Home > Software design >  Material Container Transform animation using floating action button not working smoothly
Material Container Transform animation using floating action button not working smoothly

Time:11-13

I am trying to open a fragment by clicking on floating action button using material container transform animation. I have implemented the animation but it is not working as I expected.

problem

When navigating from one fragment A to Fragment B, the floating action button is still visible (enlarged for a brief second) when Fragment B is being opened.

What changes do I make in the animation so that the transition from floating action button to Fragment B feels more smooth? or How do I hide the enlarged floating action button when navigating to Fragment B? Below is the code of Fragments and layouts for reference.

Fragment A layout:

<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".ui.home.HomeFragment">

<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:id="@ id/create_btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:transitionName="my_transition"
    android:src="@drawable/ic_round_add_24"
    android:layout_gravity="bottom|end"
    android:layout_margin="@dimen/dimen_16"
    android:contentDescription="New Task"
</androidx.coordinatorlayout.widget.CoordinatorLayout>

Fragment A code:

class FragmentA : Fragment() {

private var _binding: FragmentABinding? = null
private val binding get() = _binding!!

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    exitTransition = Hold()
}

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View {
    _binding = FragmentABinding.inflate(inflater)

    binding.createTask.setOnClickListener {
        val extras = FragmentNavigatorExtras(binding.createTask to "my_transition")
        findNavController().navigate(R.id.action_FragmentA_to_FragmentB,null,null,extras)
    }

    return binding.root
}

override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
}

}

Fragment B layout:

<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:transitionName="my_transition"
tools:context=".ui.edit.EditTaskFragment">

<com.google.android.material.appbar.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="@dimen/toolbar_size"
    app:liftOnScroll="true">
    <FrameLayout
        android:layout_width="match_parent"
        android:paddingHorizontal="@dimen/dimen_16"
        android:layout_height="match_parent">
        <ImageButton
            android:id="@ id/close"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_baseline_close_24"
            android:background="?attr/selectableItemBackgroundBorderless"
            android:layout_gravity="start|center_vertical"
            app:tint="?attr/colorPrimary" />

        <com.google.android.material.button.MaterialButton
            android:id="@ id/save"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="end|center_vertical"
            style="@style/Widget.Material3.Button.TonalButton"
            android:text="Save"
            android:minWidth="0dp"
            android:minHeight="0dp"/>
    </FrameLayout>
</com.google.android.material.appbar.AppBarLayout>

<androidx.core.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
        android:textAlignment="center"
        android:text="This is new Fragment"/>

</androidx.core.widget.NestedScrollView>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

Fragment B code:

class FragmentB : Fragment() {

private var _binding: FragmentBBinding? = null
private val binding get() = _binding!!

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    sharedElementEnterTransition = MaterialContainerTransform()
}

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View {
    _binding = FragmentBBinding.inflate(inflater)

    return binding.root
}

override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
}

}

CodePudding user response:

Solved the problem!! Just set startContainerColor and endContainerColor parameter in materialContainerTransform to surface color and then the fab transition is done more smoothly

Replace sharedElementEnterTransition in FragmentB with this:

sharedElementEnterTransition = MaterialContainerTransform().apply {
        startContainerColor = requireContext().getColorFromAttr(com.google.android.material.R.attr.colorSurface)
        endContainerColor = requireContext().getColorFromAttr(com.google.android.material.R.attr.colorSurface)
    }
  • Related