You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Fragment B返回时CollapsingToolbarLayout显示异常问题

问题:从Fragment B返回时CollapsingToolbarLayout出现闪烁异常

Fragment A包含CollapsingToolbarLayout,页面滚动时顶部Toolbar会折叠。点击页面底部按钮跳转到Fragment B,从B返回A时,B会从导航栈移除,A会回到之前滚动到底部的位置,但此时本该隐藏的Toolbar会先显示再折叠,出现闪烁异常。


Fragment A布局代码

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/coordinator"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            style="?attr/collapsingToolbarLayoutLargeStyle"
            android:layout_width="match_parent"
            android:layout_height="280dp"
            android:fitsSystemWindows="true"
            app:contentScrim="?android:colorBackground"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
            app:scrimVisibleHeightTrigger="70dp"
            app:statusBarScrim="?android:colorBackground">

            <View
                android:layout_width="match_parent"
                android:layout_height="300dp"
                android:background="#ff0000"
                android:fitsSystemWindows="true" />

            <com.google.android.material.appbar.MaterialToolbar
                android:id="@+id/topAppBar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:elevation="0dp"
                android:fitsSystemWindows="false"
                app:layout_collapseMode="pin"
                app:layout_scrollFlags="scroll|enterAlways"
                app:navigationIcon="@drawable/chevron_back"
                app:navigationIconTint="#00ff00" />
        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clipToPadding="false"
        android:fillViewport="true"
        android:orientation="vertical"
        android:paddingHorizontal="@dimen/content_padding"
        android:paddingTop="0dp"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:id="@+id/short_description"
                style="@style/body_gray"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginVertical="8dp"
                android:text="@string/lorem_ipsum" />
            <Button
                android:id="@+id/next"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginVertical="8dp"
                android:text="Next" />

        </LinearLayout>
    </androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

Fragment A代码

class FragmentA: Fragment() {
    private var _binding: FragmentABinding? = null

    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View {

        _binding = FragmentABinding.inflate(inflater, container, false)

        binding.topAppBar.setNavigationOnClickListener {
            findNavController().popBackStack()
        }

        return binding.root
    }

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

        binding.next.setOnClickListener {
            findNavController().navigate(R.id.action_A_to_B)
        }
    }
}

导航动作配置

<action
    android:id="@+id/action_A_to_B"
    app:destination="@id/fragmentb"
    app:enterAnim="@anim/slide_in"
    app:exitAnim="@anim/slide_out"
    app:popEnterAnim="@anim/pop_in"
    app:popExitAnim="@anim/pop_out"
    app:launchSingleTop="true"/>

解决方案

方案1:手动保存并恢复AppBar滚动状态

在Fragment A中监听AppBar偏移量,返回时直接恢复状态,避免过渡动画期间的状态异常:

private var appBarOffset = 0

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

    // 记录AppBar的滚动偏移
    binding.appbar.addOnOffsetChangedListener { _, offset ->
        appBarOffset = offset
    }

    // 监听从B返回的事件,恢复AppBar状态
    findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<Boolean>("backFromB")?.observe(viewLifecycleOwner) {
        binding.appbar.setExpanded(false, false)
        binding.appbar.setSelectedTabScrollPosition(appBarOffset)
    }

    binding.next.setOnClickListener {
        findNavController().navigate(R.id.action_A_to_B)
    }
}

同时在Fragment B的返回逻辑中传递状态通知:

// Fragment B的返回按钮点击事件
binding.back.setOnClickListener {
    findNavController().previousBackStackEntry?.savedStateHandle?.set("backFromB", true)
    findNavController().popBackStack()
}

方案2:移除CollapsingToolbarLayout的snap标志

snap标志会让AppBar自动调整到完全展开或折叠状态,过渡动画时容易引发闪烁,移除后可避免该问题:

app:layout_scrollFlags="scroll|exitUntilCollapsed"

方案3:在Resume时强制AppBar保持折叠状态

在Fragment A的onResume方法中,强制AppBar处于折叠状态,跳过过渡动画:

override fun onResume() {
    super.onResume()
    binding.appbar.post {
        binding.appbar.setExpanded(false, false)
    }
}

内容的提问来源于stack exchange,提问作者P1x

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 22:44:59