提问人:Andy Johnson 提问时间:11/5/2023 最后编辑:Andy Johnson 更新时间:11/5/2023 访问量:76
链接首选项屏幕
Linking preference screens
问:
tl/dr:我无法获得首选项屏幕以链接到另一个首选项屏幕。我收到运行时错误。
场景:我有一个工作 Xamarin/Android 应用,它使用 AndroidX.Preference 类通过单个首选项 xml 资源和片段实现首选项活动。这工作正常。我想将一些更高级的首选项拆分到一个单独的首选项屏幕中,如此处所述,以提高可用性。
问题:应用从 nuget 导入 Xamarin.AndroidX.Preference v1.2.1.2。在实现了链接文章(上面)中描述的方法以及调用首选项活动的代码后,当我运行它时,链接(“根”)首选项屏幕按预期出现。当我单击链接首选项时,Android 无法实例化链接首选项屏幕的片段,并抛出异常并显示消息“”。我不明白为什么会这样,因为这个类肯定存在。AndroidX.Fragment.App.Fragment.InstantiationException
Unable 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:fragment
com.companyname.app1
App1
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。
为上面的代码量道歉,但我没有想法。有人可以启发我做错了什么吗?谢谢。
答:
问题是 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 包后,需要重新生成应用。若要重新生成应用,请单击“生成>重新生成解决方案”菜单项。
重新构建应用程序后,您应该能够实例化链接首选项屏幕的片段,而不会出现任何问题。
评论
AdvancedPreferencesFragment