解决方案 1:原生 PreferenceFragment 和 AppCompatActivity
在 AndroidStudio 中,选择 File > New Project >...> SettingsActivity。此模板使用一种解决方法,将原生 PreferenceFragment 改造为与 AppCompatActivity 一起使用,类似于 support.v4.Fragment 或 support.v7.PreferenceFragmentCompat。
- 专业版:您现在可以在
AppCompat 应用程序。这是使用 AS 模板时的快速方法,您可以坚持现有的 Preference 文档和工作流程。
- 缺点:改造不是很直观或干净。此外,由于通常建议在可用的情况下使用支持库,因此我不确定这种方法是否具有前瞻性。
解决方案 2:support.v7.preference.PreferenceFragmentCompat 与 AppCompatActivity
- 专业版:最大限度地提高兼容性
- 缺点:有很多差距需要弥补。此外,这可能不适用于任何现有的偏好扩展库(例如
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 中定义一个preferenceTheme,否则运行您的应用会引发异常。
<!-- 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 不再由框架管理。在preference.xml 中定义PreferenceScreen(如docs 中所述)将显示该条目,但单击它不会执行任何操作。现在由您来处理显示和导航子屏幕。无聊。
有一种方法(描述为here),将PreferenceFragmentCompat.OnPreferenceStartScreenCallback 添加到您的PreferenceFragmentCompat。虽然这种方法可以快速实施,但它只是交换了现有偏好片段的内容。缺点是:没有返回导航,你总是“在顶部”,这对用户来说不是很直观。
在另一种方法中(描述为here),您还必须管理后退堆栈以实现预期的后退导航。这使用preferenceScreen.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: 制定自己的偏好也从琐碎变得无聊。 DialogPreference 现在删除了处理实际对话框的所有内容。该位现在位于PreferenceDialogFragmentCompat。所以你必须对两者进行子类化,然后自己创建对话框并显示它(解释为here)。
查看PreferenceFragmentCompat.onDisplayPreferenceDialog() 的源代码表明它知道如何处理恰好2 个对话框首选项(EditTextPreference、ListPreference),其他一切您必须使用OnPreferenceDisplayDialogCallbacks 自己实现...有人想知道,为什么没有处理DialogPreference 的子类的功能!
这里有一些代码实现了大多数这些变通方法并将它们装箱到一个 lib 模块中:
https://github.com/mstummer/extended-preferences-compat.git
主要意图是:
- 无需在每个应用程序/项目中扩展和摆弄
Activity 和PreferenceFragment。 preference.xml 现在再次成为每个项目中唯一需要更改/维护的文件。
- 按预期处理和显示
PreferenceScreens(子屏幕)。
- 取消拆分
DialogPreference 以恢复本机行为。
- 处理和显示
DialogPreference 的任何子类。
不要认为开箱即用就足够干净,但在处理类似问题时它可能会给您一些提示。试一试,如果您有任何建议,请告诉我。