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

Jetpack Navigation预测返回手势取消后选抽屉项触发异常

Jetpack Navigation预测返回手势取消后抽屉菜单跳转崩溃问题

我基于Jetpack Navigation实现了预测返回动画的简化Demo,抽屉关闭和Fragment切换时的预测返回手势动画均正常工作,但在取消返回操作(从FragmentTwo/FragmentThree滑动返回预览FragmentOne但未完成返回)后,点击抽屉菜单中的选项会触发崩溃。

重现步骤

  • 从FragmentOne导航到FragmentTwo或FragmentThree
  • 触发预测返回手势,滑动显示FragmentOne的预览状态后取消返回(不完成返回操作)
  • 打开侧边抽屉菜单,点击任意Fragment选项,应用崩溃

崩溃日志

java.lang.IllegalArgumentException: saveBackStack("ebcca18f-eabb-424e-97b3-63de5fc97b85") must be self contained and not reference fragments from non-saved FragmentTransactions. Found reference to fragment FragmentOne{f7891b} (005b0355-e5f5-48d6-9ea8-df260bf6f4f4 id=0x7f080136 tag=1e300225-9207-4967-9e10-11f7bbd1ba65) in BackStackEntry{1ecf460 #4 ebcca18f-eabb-424e-97b3-63de5fc97b85} that were previously added to the FragmentManager through a separate FragmentTransaction.
at androidx.fragment.app.FragmentManager.saveBackStackState(FragmentManager.java:2450)
at androidx.fragment.app.FragmentManager$SaveBackStackState.generateOps(FragmentManager.java:3776)
at androidx.fragment.app.FragmentManager.generateOpsForPendingActions(FragmentManager.java:2332)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1999)
at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:702)

代码实现

MainActivity

class MainActivity : AppCompatActivity() {
    private lateinit var appBarConfiguration : AppBarConfiguration
    private lateinit var binding: MainActivityBinding

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

        binding = MainActivityBinding.inflate(layoutInflater)
        setContentView(binding.root)

        setSupportActionBar(binding.toolbar)

        val host: NavHostFragment = supportFragmentManager
                .findFragmentById(R.id.nav_host_fragment) as NavHostFragment
        val navController = host.navController

        appBarConfiguration = AppBarConfiguration(
            setOf(R.id.fragmentOne, R.id.fragmentTwo, R.id.fragmentThree),
                binding.drawerLayout)

        setupActionBarWithNavController(navController, appBarConfiguration)
        binding.navView.setupWithNavController(navController)

    }

    override fun onSupportNavigateUp(): Boolean {
        return findNavController(R.id.nav_host_fragment).navigateUp(appBarConfiguration)
    }
}

FragmentOne

class FragmentOne: Fragment() {
    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ) = FragmentSampleBinding.inflate(inflater, container, false).also {
        it.content.text = this::class.java.simpleName
    }.root
}

FragmentTwo

class FragmentTwo : Fragment() {
    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ) = FragmentSampleBinding.inflate(inflater, container, false).also {
        it.content.text = this::class.java.simpleName
    }.root
}

FragmentThree

class FragmentThree : Fragment() {
    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ) = FragmentSampleBinding.inflate(inflater, container, false).also {
        it.content.text = this::class.java.simpleName
    }.root
}

res/layout/main_activity.xml

<androidx.drawerlayout.widget.DrawerLayout
    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/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:openDrawer="start"
    tools:context="com.example.predictiveback.MainActivity">

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

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/colorPrimary"
            android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar" />

        <fragment
            android:id="@+id/nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/mobile_navigation" />

    </LinearLayout>

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="left"
        app:menu="@menu/nav_drawer_menu" />
</androidx.drawerlayout.widget.DrawerLayout>

res/layout/fragment_sample.xml

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/content"
        android:layout_gravity="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAlignment="center"
        android:textSize="52sp" />

</FrameLayout>

res/navigation/mobile_navigation.xml

<?xml version="1.0" encoding="utf-8"?>
<navigation 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"
    app:startDestination="@+id/fragmentOne">
    <fragment
        android:id="@+id/fragmentOne"
        android:name="com.example.predictiveback.FragmentOne"
        android:label="Fragment One"
        tools:layout="@layout/fragment_sample"/>

    <fragment
        android:id="@+id/fragmentTwo"
        android:name="com.example.predictiveback.FragmentTwo"
        android:label="Fragment Two"
        tools:layout="@layout/fragment_sample"/>

    <fragment
        android:id="@+id/fragmentThree"
        android:name="com.example.predictiveback.FragmentThree"
        android:label="Fragment Three"
        tools:layout="@layout/fragment_sample"/>
</navigation>

res/menu/nav_drawer_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@id/fragmentOne"
        android:icon="@drawable/ic_home"
        android:title="Fragment One" />

    <item
        android:id="@id/fragmentTwo"
        android:icon="@drawable/ic_android"
        android:title="Fragment Two" />


    <item
        android:id="@+id/fragmentThree"
        android:icon="@drawable/ic_android"
        android:title="Fragment Three" />

</menu>

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    <application
        android:allowBackup="false"
        android:icon="@mipmap/ic_launcher"
        android:label="Predictive Back Demo"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:enableOnBackInvokedCallback="true">

        <activity android:name="com.example.predictiveback.MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <nav-graph android:value="@navigation/mobile_navigation" />
        </activity>


    </application>

</manifest>

依赖配置

ext {
        kotlinVersion = '2.0.0'
        appCompatVersion = "1.7.0"
        recyclerVersion = "1.3.2"
        materialVersion = "1.12.0"
        navigationVersion = '2.7.7'
        constraintLayoutVersion = "2.1.4"
    }
    

dependencies {
    implementation "com.google.android.material:material:$rootProject.materialVersion"
    implementation "androidx.appcompat:appcompat:$rootProject.appCompatVersion"
    implementation "androidx.recyclerview:recyclerview:$rootProject.recyclerVersion"
    implementation("androidx.drawerlayout:drawerlayout:1.2.0")
    implementation "androidx.constraintlayout:constraintlayout:$rootProject.constraintLayoutVersion"

    implementation "androidx.navigation:navigation-fragment-ktx:$rootProject.navigationVersion"
    implementation "androidx.navigation:navigation-ui-ktx:$rootProject.navigationVersion"
    
    implementation("androidx.activity:activity-ktx:1.9.1")
    implementation("androidx.fragment:fragment-ktx:1.8.2")
    implementation("androidx.transition:transition-ktx:1.5.1")
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 17:27:01