所以问题:
如何最好地实现AppCompat应用程序的首选项(PreferenceFragment和AppCompatAcitivity不兼容)?
以下是几个相关问题:
> Preference sub-screen not opening when using support.v7.preference
> How to move back from Preferences subscreen to main screen in PreferenceFragmentCompat?
> PreferenceFragmentCompat requires preferenceTheme to be set
> How do I create custom preferences using android.support.v7.preference library?
官方文件:
> http://developer.android.com/guide/topics/ui/settings.html
> http://developer.android.com/reference/android/support/v7/preference/Preference.html
解决方法
在AndroidStudio中,选择文件>新项目> …> SettingsActivity.此模板使用一种解决方法来改造本机PreferenceFragment以使用AppCompatActivity,类似于support.v4.Fragment或support.v7.PreferenceFragmentCompat.
> Pro:您现在可以在其中使用本机首选项功能
AppCompat应用使用AS模板时,这是一个快速的方法,您可以坚持现有的“首选项”文档和工作流.
Con:改装不是非常直观或干净.此外,由于通常建议使用可用的支持库,我不知道这种做法是如何面向未来的.
解决方案2:support.v7.preference.PreferenceFragmentCompat与AppCompatActivity
Pro:最大化兼容性
Con:有很大的差距来弥补.此外,这可能不适用于任何现有的preference-extensions-libs(例如ColorPicker或FontPreferences).
如果您选择不使用解决方案1(我仍然不确定这两者中哪一个更具有未来证据),那么在使用support.v7.preference时有一些缺点.
下面提到使用解决方案2的重要缺陷.
依赖关系:
dependencies { ... compile 'com.android.support:appcompat-v7:23.1.1' compile 'com.android.support:preference-v7:23.1.1' compile 'com.android.support:support-v4:23.1.1' }
主题:
您需要在styles.xml中定义一个preferencesTheme,否则运行您的应用程序会引发异常.
<!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light"> <!-- Customize your theme here. --> <item name="preferenceTheme">@style/PreferenceThemeOverlay</item> </style>
您可能希望将其分成7/14/21的不同风格.在撰写本文时,很多人抱怨这是错误的.有一个非常全面的答案here.
行为变化:使用本机首选项是非常简单的:所有您需要做的是定义/维护您的preferences.xml,并在PreferenceFragment中使用addPreferencesFromResource(R.xml.preferences).通过子类DialogPreference轻松完成自定义首选项,然后只是在preferences.xml … bam中引用.
不幸的是,support.v7.preference已经将与处理Fragment相关的所有内容都删除了,从而使其松散了很多内置的功能.而不是仅仅维护一个XML,现在你必须要分类并重写很多东西,所有这些都是不幸的.
PreferenceScreens:PreferenceScreens不再由框架管理.在您的preferences.xml(如docs中所述)中定义一个PreferenceScreen将显示该条目,但单击它不会执行任何操作.现在由您处理显示和导航子屏幕.无聊.
有一种方法(描述为here),将PreferenceFragmentCompat.OnPreferenceStartScreenCallback添加到您的PreferenceFragmentCompat.虽然这种方法快速实现,但它只是交换现有偏好片段的内容.缺点是:没有后退导航,你总是在顶部,这对用户来说不是很直观.
在另一种方法(描述here)中,您还必须管理后端堆栈,以实现预期的导航.这将使用preferencesScreen.getKey()作为每个新创建/显示的片段的根.
在这样做的时候,您也可能会默认偏爱PreferenceFragments是透明的,并且相互之间奇怪地相加.人们倾向于重写PreferenceFragmentCompat.onViewCreated()来添加类似的东西
// Set the default white background in the view so as to avoid transparency view.setBackgroundColor(ContextCompat.getColor(getContext(),R.color.background_material_light));
自定义对话框:自己的偏好也从微不足道,无聊. DialogPreference现在有任何处理实际对话框的东西,被删除.那位现在住在PreferenceDialogFragmentCompat.所以你必须要分两类,然后处理创建对话框并自己显示(说明here).
查看PreferenceFragmentCompat.onDisplayPreferenceDialog()的源代码显示它知道如何处理两个对话框首选项(EditTextPreference,ListPreference),其他所有你必须实现自己使用OnPreferenceDisplayDialogCallbacks …一个奇迹,为什么没有功能处理DialogPreference子类!
以下是一些实现大多数这些变通方法的代码,并将它们放在lib模块中:
https://github.com/mstummer/extended-preferences-compat.git
主要目的是:
>删除在每个应用程序/项目中扩展和调整活动和首选项分段的需要. preference.xml现在再次是唯一的每个项目文件进行更改/维护.
>按预期处理并显示偏好屏幕(子屏幕).
> Un-split DialogPreference可恢复原生行为.
>处理和显示DialogPreference的任何子类.
不要以为刚刚使用开箱即可,但在处理类似问题时可能会给您一些提示.给它一个旋转,让我知道,如果你有任何建议.