【问题标题】:PreferenceFragments not in the same FragmentManager?PreferenceFragments 不在同一个 FragmentManager 中?
【发布时间】:2020-11-27 23:35:12
【问题描述】:

我们有一个PreferenceFragmentCompat,通过点击偏好,我们希望从当前的PreferenceFragmentCompat 切换到新的PreferenceFragmentCompat。 (在新屏幕上进行某些设置)。

但是,无论我们尝试了什么,我们都会遇到以下错误:

片段声明的目标片段不属于这个 片段管理器

MainActivity.kt

class MainActivity : AppCompatActivity(), ActivityCompat.OnRequestPermissionsResultCallback, PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val navView: BottomNavigationView = findViewById(R.id.nav_view)

        val navController = findNavController(R.id.nav_host_fragment)
        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.
        val appBarConfiguration = AppBarConfiguration(
            setOf(
                R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_preferences
            )
        )

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

    override fun onPreferenceStartFragment(caller: PreferenceFragmentCompat, pref: Preference): Boolean {
        val args = pref.extras
        val fragment = supportFragmentManager.fragmentFactory.instantiate(
            classLoader,
            pref.fragment)
        fragment.arguments = args
        fragment.setTargetFragment(caller, 0)
        // Replace the existing Fragment with the new Fragment
        supportFragmentManager.beginTransaction()
            .replace(R.id.nav_host_fragment, fragment)
            .addToBackStack(null)
            .commit()
        return true
    }
}

PreferenceFragement1.kt

class PreferencesFragment1 : PreferenceFragmentCompat() {

    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        setPreferencesFromResource(R.xml.preferences1, rootKey)
    }
}

PreferenceFragment2.kt

class PreferenceFragment2 : PreferenceFragmentCompat() {

    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        setPreferencesFromResource(R.xml.preferences2, rootKey)
    }
}

Preferences1.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <PreferenceCategory
        android:title="Category"
        app:iconSpaceReserved="false">

        <Preference
            app:key="pref2"
            app:iconSpaceReserved="false"
            android:title="Open"
            app:fragment="com.testapp.ui.preferences.Preference2"/>

    </PreferenceCategory>
</PreferenceScreen>

Preferences2.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</PreferenceScreen>

堆栈跟踪显示如下:

java.lang.IllegalStateException: Fragment Preference2{496ebb9} (1b91d8df-58c0-485a-96f9-d392fcef528b) id=0x7f09008d} declared target fragment Preference1{b6337c1} (97aa1b0e-d5fa-4995-b0ba-e89ad0ea5ce0) id=0x7f09008d} that does not belong to this FragmentManager!
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1148)
        at androidx.fragment.app.FragmentTransition.addToFirstInLastOut(FragmentTransition.java:1255)
        at androidx.fragment.app.FragmentTransition.calculateFragments(FragmentTransition.java:1138)
        at androidx.fragment.app.FragmentTransition.startTransitions(FragmentTransition.java:136)
        at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1989)
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1947)
        at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
        at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6718)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:491)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

我们正在使用androidx.preference:preference-ktx:1.1.1。 谁能给我们一个简明的解释究竟是什么导致了这个问题,以及我们如何解决它?

我们已经查看了以下(相关)帖子,但没有任何成功:

【问题讨论】:

    标签: android kotlin mobile fragment fragmentmanager


    【解决方案1】:

    当您通过导航图创建片段时,它是NavHostFragment 的子片段。它具体不是活动的supportFragmentManager。这就是找不到目标片段的原因 - 您使用了错误的 FragmentManager。

    但是,您在使用导航时不应使用app:fragmentonPreferenceStartFragment。相反,您的 PreferencesFragment1 应该在您的 Preference 上设置一个点击监听器并让它直接调用 navigate()

    class PreferencesFragment1 : PreferenceFragmentCompat() {
    
        override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
            setPreferencesFromResource(R.xml.preferences1, rootKey)
            findPreference<Preference>("pref2")?.setOnPreferenceClickListener {
                // Use whatever ID that is associated with
                // PreferenceFragment2 in your navigation graph
                findNavController().navigate(R.id.pref2)
            }
        }
    }
    

    Preferences1.xml

    <?xml version="1.0" encoding="utf-8"?>
    <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <PreferenceCategory
            android:title="Category"
            app:iconSpaceReserved="false">
    
            <Preference
                app:key="pref2"
                app:iconSpaceReserved="false"
                android:title="Open"/>
    
        </PreferenceCategory>
    </PreferenceScreen>
    

    【讨论】:

    • 是的,谢谢您的回答!顺便说一句,你的忠实粉丝,作为谷歌员工,我想知道文档是否可以在某个时候更新? developer.android.com/guide/topics/ui/settings/… 概述部分讨论了使用 Jetpack 库中的 PreferenceFragmentCompat,但是当我们进入子 Preference Screens 的上述部分时,我们正在讨论覆盖 Activity 方法等的“旧”方式,并且没有在 Jetpack/Navigation Component 世界中实现嵌套设置屏幕的指南。
    • 我花了 3 个小时寻找这个答案。我什至对 android sample repo github.com/android/user-interface-samples 做了一些研究。有人应该把它放在官方文档中
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-14
    • 2012-07-03
    • 2014-03-01
    • 1970-01-01
    相关资源
    最近更新 更多