链接首选项屏幕

Linking preference screens

提问人:Andy Johnson 提问时间:11/5/2023 最后编辑:Andy Johnson 更新时间:11/5/2023 访问量:76

问:

tl/dr:我无法获得首选项屏幕以链接到另一个首选项屏幕。我收到运行时错误。

场景:我有一个工作 Xamarin/Android 应用,它使用 AndroidX.Preference 类通过单个首选项 xml 资源和片段实现首选项活动。这工作正常。我想将一些更高级的首选项拆分到一个单独的首选项屏幕中,如此所述,以提高可用性。

问题:应用从 nuget 导入 Xamarin.AndroidX.Preference v1.2.1.2。在实现了链接文章(上面)中描述的方法以及调用首选项活动的代码后,当我运行它时,链接(“根”)首选项屏幕按预期出现。当我单击链接首选项时,Android 无法实例化链接首选项屏幕的片段,并抛出异常并显示消息“”。我不明白为什么会这样,因为这个类肯定存在。AndroidX.Fragment.App.Fragment.InstantiationExceptionUnable to instantiate fragment com.companyname.app1.AdvancedPreferencesFragment: make sure class name exists

示例代码:我创建了一个简单的示例应用程序,它展示了我看到的问题,并且尽可能简洁。以下是首选项活动.cs:

namespace App1
{
    [Android.App.Activity(Label = "PreferencesActivity")]
    public class PreferencesActivity : AndroidX.AppCompat.App.AppCompatActivity//, AndroidX.Preference.PreferenceFragmentCompat.IOnPreferenceStartFragmentCallback
    {
        protected override void OnCreate(Android.OS.Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.preferences_activity);
            SupportFragmentManager.BeginTransaction().Replace(Resource.Id.preferences_fragment_container, new RootPreferencesFragment()).Commit();
        }
    }
}

下面是其preference_activity.xml布局资源:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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="wrap_content"
    android:orientation="vertical">
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/preferences_fragment_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

这将实例化,即:RootPreferencesFragment

namespace App1
{
    public class RootPreferencesFragment : AndroidX.Preference.PreferenceFragmentCompat
    {
        public override void OnCreate(Android.OS.Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
        }

        public override void OnCreatePreferences(Android.OS.Bundle savedInstanceState, string rootKey)
        {
            SetPreferencesFromResource(Resource.Xml.preferences_root, rootKey);
        }
    }
}

及其对应的 XML 资源:preferences_root.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <androidx.preference.SwitchPreference
        android:key="pref1"
        android:title="Prefercence 1"/>
    <androidx.preference.Preference
        android:title="Advanced"
        app:fragment="com.companyname.app1.AdvancedPreferencesFragment"/>
</androidx.preference.PreferenceScreen>

上面的链接元素指定了一个名为 的片段,该片段是链接首选项屏幕片段的全名:<Preference>com.companyname.app1.AdvancedPreferencesFragment

namespace App1
{
    public class AdvancedPreferencesFragment : AndroidX.Preference.PreferenceFragmentCompat
    {
        public override void OnCreate(Android.OS.Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
        }

        public override void OnCreatePreferences(Android.OS.Bundle savedInstanceState, string rootKey)
        {
            SetPreferencesFromResource(Resource.Xml.preferences_advanced, rootKey);
        }
    }
}

及其对应的 XML 资源:preferences_advanced.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <androidx.preference.SwitchPreference
        android:key="pref2"
        android:title="Advanced Prefercence 2"/>
</androidx.preference.PreferenceScreen>

我尝试过:

我认为问题出在链接首选项元素的属性值上,该属性用于实例化链接片段。应用程序的包名称是,C#命名空间是,所以我尝试了此属性的以下值:app:fragmentcom.companyname.app1App1

  • com.companyname.App1.AdvancedPreferencesFragment
  • com.companyname.app1.AdvancedPreferencesFragment
  • com.companyname.app1.App1.AdvancedPreferencesFragment
  • com.companyname.app1.app1.AdvancedPreferencesFragment
  • App1.AdvancedPreferencesFragment
  • app1.AdvancedPreferencesFragment
  • AdvancedPreferencesFragment

它们都不起作用,它们都给了我相同的异常,与属性值匹配的消息文本略有不同。

我尝试将空的默认构造函数添加到两个片段类中,但这没有任何区别。

编辑添加:我尝试在类中实现如下:AndroidX.Preference.PreferenceFragmentCompat.IOnPreferenceStartFragmentCallback.OnPreferenceStartFragment()PreferencesActivity

bool IOnPreferenceStartFragmentCallback.OnPreferenceStartFragment(AndroidX.Preference.PreferenceFragmentCompat caller, AndroidX.Preference.Preference pref)
{
    // Instantiate the new Fragment.
    var fragment = SupportFragmentManager.FragmentFactory.Instantiate(this.ClassLoader, pref.Fragment);
    fragment.Arguments = pref.Extras;
    fragment.SetTargetFragment(caller, 0);

    // Replace the existing Fragment with the new Fragment.
    SupportFragmentManager.BeginTransaction()
            .Replace(Resource.Id.preferences_fragment_container, fragment)
            .AddToBackStack(null)
            .Commit();
    return true;
}

但我仍然得到同样的执行.FragmentFactory.Instantiate()

VS 2022 x64 v17.7.5 v17.7.5 和 Xamarin 11 x64。我的示例应用程序面向 Android 13 / API 33,最低版本为 Android 10 / API 29。

为上面的代码量道歉,但我没有想法。有人可以启发我做错了什么吗?谢谢。

Android xamarin android-fragments xamarin.android

评论

0赞 Guangyu Bai - MSFT 11/9/2023
我在我这边测试了该方法,但它无法获得类。建议在 GitHub 上将其作为问题报告。AdvancedPreferencesFragment
0赞 Andy Johnson 11/10/2023
@GuangyuBai-MSFT 就可以了。

答:

-1赞 James Taylor 11/5/2023 #1

问题是 Xamarin.AndroidX的。首选项 v1.2.1.2 NuGet 包与最新版本的 AndroidX Fragment 库不兼容。若要解决此问题,需要升级 Xamarin。AndroidX的。将 NuGet 包至少首选为 v1.3.0.2。

升级 NuGet 包后,需要重新生成应用。重新构建应用程序后,您应该能够实例化链接首选项屏幕的片段,而不会出现任何问题。

下面是升级 Xamarin.AndroidX.Preference NuGet 包的步骤:

在 Visual Studio 中打开 NuGet 包管理器。 搜索 Xamarin.AndroidX.Preference NuGet 包。 选择 Xamarin.AndroidX。首选项 v1.3.0.2 NuGet 包,然后单击“安装”按钮。 单击“确定”按钮确认安装。 安装 NuGet 包后,需要重新生成应用。若要重新生成应用,请单击“生成>重新生成解决方案”菜单项。

重新构建应用程序后,您应该能够实例化链接首选项屏幕的片段,而不会出现任何问题。

评论

0赞 Andy Johnson 11/5/2023
感谢您的回复!我已经按照您的建议做了,但我没有看到 Xamarin.AndroidX.Preference 的 v1.3.0.2。v1.2.1.2 似乎是最新版本。我在这里错过了什么?我的示例应用程序面向 Android 13 / API 33,最低版本为 Android 10 / API 29(如果相关)。
0赞 Andy Johnson 11/5/2023
后续添加包管理器的源设置为 nuget.org。v1.2.1.2 在 nuget.org/packages/Xamarin.AndroidX.Preference/ 显示为最新版本...
0赞 Andy Johnson 11/5/2023
好的,所以没有 Xamarin 的 v1.3.0.2。AndroidX的。Preference 或 AndroidX.Preference。鉴于这一点,以及文本的结构,以及您对 SO 上其他问题的回答,我将假设您使用 LLM 创建了您的答案。这并不酷 - 请不要这样做。