将 AppCompat 主题应用于首选项碎片中的单个首选项

2022-09-02 22:09:02

我一直在努力使我拥有与我的应用程序的其余部分相同的基于材料的主题和样式(通过AppCompat)。我用来管理所有应用程序设置的如下所示:PreferenceFragmentPreferenceFragment

enter image description here

从上面的屏幕截图中可以看出,我能够通过使用 、 和其他一些属性来自定义 。我的主题如下:PreferenceFragmentcolorAccentcolorPrimaryPreferenceFragment

<style
    name="settingsTheme"
    parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="colorPrimary">@color/blue_grey_500</item>
    <item name="colorAccent">@color/blue_grey_500</item>
    <item name="android:textColor">@color/black_text_alt</item>
    <item name="android:textColorSecondary">@color/black_secondary_text</item>
</style>

但是,尽管我尽了最大的努力,我还是无法将主题应用于我的 ,例如 和 ;所有首选项仍保留标准的 AppCompat 主题:PreferenceFragmentListPreferenceEditTextPreference

enter image description here

我发现了一篇2年前的帖子,讨论了这个问题,尽管没有真正的解决方案:如何将主题应用于<PreferenceScreen><PreferenceCategory的元素>

我想知道自AppComat V21发布以来,是否有人能够成功地将主题应用于首选项。如果没有,是否有任何可行的解决方法可用于将自定义主题应用于各个首选项?


答案 1

更新:我做了一个库来解决这个问题(使用AppCompat r22):https://github.com/consp1racy/android-support-preference


使用这段代码创建对话框的扩展:ListPreferenceDialogPreference

mBuilder = new AlertDialog.Builder(context)
    .setTitle(mDialogTitle)
    .setIcon(mDialogIcon)
    .setPositiveButton(mPositiveButtonText, this)
    .setNegativeButton(mNegativeButtonText, this);

如您所见,构造函数未提供第二个可选参数。这意味着对话框将按活动主题在其属性中的任何内容为主题。AlertDialog.Builderint themeandroid:alertDialogTheme

现在,您必须为对话框创建一个自定义主题,该主题源自如下所示:Theme.AppCompat.Dialog

<style name="Theme.YourApp.Dialog.Alert" parent="Theme.AppCompat.Light.Dialog">
  <item name="android:windowBackground">@android:color/transparent</item>
  <item name="android:windowContentOverlay">@null</item>
  <item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item>
  <item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item>
  <item name="colorAccent">@color/accent_yourapp</item>
  <item name="colorPrimary">@color/primary_yourapp</item>
  <item name="colorPrimaryDark">@color/primary_dark_yourapp</item>
</style>

问题 1:上述解决方案将不起作用,因为它不会扩展,而是调用铃声选择器意图,因此它始终根据系统进行主题。看看这个答案: 铃声高级主题 所以我们可以把它标记为已解决。RingtonePreferenceListPreference

问题 2:“应用比较”对话框缺少标题。到目前为止,我还没有找到解决这个问题的方法。的确,我看起来不够努力。让我们忽略标题缺失作为一个小问题。

问题 3:单选按钮可绘制对象不会发生更改,因此图形在被动和主动(有色)状态之间不一致 - 所有图形都是彩色的(不仅仅是您!重新按下的那个)或全部是灰色的。现在这真的很烦人

问题2和3迫使我走另一条路 - 我的对话主题在API 14 +上看起来像这样

<style name="Theme.MyApp.Dialog.Alert" parent="android:Theme.DeviceDefault.Light.Dialog.MinWidth">
  <item name="android:windowBackground">@android:color/transparent</item>
  <item name="android:windowContentOverlay">@null</item>
</style>

就像在API 21 +上一样

<style name="Theme.YourApp.Dialog.Alert" parent="android:Theme.DeviceDefault.Light.Dialog.MinWidth">
  <item name="android:colorPrimary">@color/primary_yourapp</item>
  <item name="android:colorPrimaryDark">@color/primary_dark_yourapp</item>
  <item name="android:colorAccent">@color/accent_yourapp</item>
</style>

这些值是通过爬网平台的源文件通过实验获得的,并经过了充分的测试。

关键是,唯一可靠的解决方案似乎是使用设备默认对话框主题。在棒棒糖之前,唯一的选择是浅色或深色的变体。在棒棒糖上,这将按预期和要求工作。

编辑:由于appcompat-v7-r21.1.0,您可以使用AppCompatDialog,它是本机的材料主题变体。AlertDialog

您可以使用提供的 AlertDialog.Builder(不要与其本机对应项混淆)来创建其实例。


答案 2

DialogPreference直接使用,因此不可能将显示的对话框切换到所有API级别的材料设计对话框(这需要使用)。android.app.AlertDialog.Builderandroid.support.v7.widget.AlertDialog.Builder

我相信现在唯一的选择是扩展和覆盖或其子类中的对话创建逻辑(并在需要时使用反射来解决私有访问器)。查看此reddit线程以及该线程的作者制作的示例AppCompatListPreferenceDialogPreference


推荐