调整 androidx.preference 对话框以遵循 Material You

问题描述 投票:0回答:4

我有两个包含首选项部分的应用程序,并且我正在使用首选项库,这是撰写本文时可用的最新版本:

    implementation "androidx.preference:preference:1.2.0-rc01"

现在,我将我的应用程序主题化为使用并遵循新的 Material3(或 Material You)主题,但我面临的一个问题是,虽然普通对话框的主题正确,但首选项部分中的对话框仅部分主题化(拐角半径)。他们显然不使用新样式,这种不一致快要了我的命:D

Normal Material You dialog Preference dialog

目前,我没有找到一种方法来为它们设置主题,而无需奇怪的解决方法,所以我将不胜感激。这是我目前的对话框样式

<!-- Dialog theme -->
<style name="ThemeOverlay.App.MaterialAlertDialog" parent="ThemeOverlay.Material3.MaterialAlertDialog">
    <item name="colorOnSurface">?colorAccent</item>
    <item name="alertDialogStyle">@style/MaterialAlertDialog.App</item>
    <item name="dialogCornerRadius">@dimen/bottom_sheet_corners</item>
</style>

<!-- Note: shape appearance doesn't work with the preference dialogs (they're not material) -->
<style name="MaterialAlertDialog.App" parent="MaterialAlertDialog.Material3">
    <item name="shapeAppearance">@style/ShapeAppearance.App.MediumComponent</item>
    <item name="shapeAppearanceOverlay">@null</item>
</style>

也许这只是等待的问题

android material-design android-preferences material-dialog material-you
4个回答
7
投票

目前,首选项对话框仍然使用

AlertDialog
来膨胀视图。以下是我在
styles.xml
中定义的内容,以将 Material3 对话框主题应用于它们:

注意: 这涵盖了大部分 MaterialAlertDialog 样式,但您仍然需要定义其他样式,例如角半径和背景/文本颜色。

<item name="alertDialogTheme">@style/ThemeOverlay.Material3.MaterialAlertDialog</item>
<item name="dialogCornerRadius">28dp</item>

4
投票

经过进一步调查,我发现,截至今天,正确设置首选项对话框主题的唯一方法是使用向 @Patrick 提出的解决方案的细微变化:

  1. 创建一个drawable,我将其命名为dialog_bg_monet.xml,包含此图层列表:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
     <item> 
         <shape> 
             <solid android:color="?attr/colorSurface" /> 
             <corners 
                 android:bottomLeftRadius="@dimen/yourcorners" 
                 android:bottomRightRadius="@dimen/yourcorners" 
                 android:topLeftRadius="@dimen/yourcorners" 
                 android:topRightRadius="@dimen/yourcorners" /> 
         </shape> 
     </item> 
     <item> 
         <shape> 
             <solid android:color="@color/m3_popupmenu_overlay_color" /> 
             <corners 
                 android:bottomLeftRadius="@dimen/yourcorners" 
                 android:bottomRightRadius="@dimen/yourcorners" 
                 android:topLeftRadius="@dimen/yourcorners" 
                 android:topRightRadius="@dimen/yourcorners" /> 
         </shape> 
     </item> 
 </layer-list>

当然,请确保在尺寸中或直接在文件中定义自定义边框半径。忽略警告。没有别的办法了

  1. 为对话框创建样式,如下所示:
    <!-- Preference dialog theme -->
    <style name="ThemeOverlay.App.MaterialAlertDialog.Monet" parent="ThemeOverlay.Material3.MaterialAlertDialog">
        <item name="alertDialogStyle">@style/MaterialAlertDialog.App</item>
        <item name="dialogCornerRadius">@dimen/yourcorners</item>
        <item name="android:background">@drawable/dialog_bg_monet</item>
    </style>
  1. 在你的主题中应用这种风格
<item name="materialAlertDialogTheme">@style/ThemeOverlay.App.MaterialAlertDialog.Monet</item>
<item name="alertDialogTheme">@style/ThemeOverlay.App.MaterialAlertDialog.Monet</item>

结果:

Monet preference dialogs

上面截图中的应用程序是开源的,您可以在这里看到完整的代码

编辑:这种方法会导致上下文菜单(长按文本时弹出的复制/粘贴菜单)出现错误。解决这个问题的方法很简单,就在这个问题


3
投票

这就是我所做的。

  1. 创建一个扩展 ListPreferenceDialogFragmentCompat 的 MaterialListPreference 类

    class MaterialListPreference : ListPreferenceDialogFragmentCompat() {
       private var mWhichButtonClicked = 0
       override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
          val context: Context? = activity
          mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE
          val builder = MaterialAlertDialogBuilder(requireActivity()).setTitle(preference.dialogTitle).setIcon(preference.dialogIcon)
            .setPositiveButton(preference.positiveButtonText, this)
            .setNegativeButton(preference.negativeButtonText, this)
          val contentView = context?.let { onCreateDialogView(it) }
          if (contentView != null) {
            onBindDialogView(contentView)
            builder.setView(contentView)
          } else {
            builder.setMessage(preference.dialogMessage)
          }
          onPrepareDialogBuilder(builder)
          return builder.create()
       }
    
       override fun onClick(dialog: DialogInterface, which: Int) {
           mWhichButtonClicked = which
       }
    
       override fun onDismiss(dialog: DialogInterface) {
           onDialogClosedWasCalledFromOnDismiss = true
           super.onDismiss(dialog)
       }
    
       private var onDialogClosedWasCalledFromOnDismiss = false
    
       override fun onDialogClosed(positiveResult: Boolean) {
           if (onDialogClosedWasCalledFromOnDismiss) {
               onDialogClosedWasCalledFromOnDismiss = false
               super.onDialogClosed(mWhichButtonClicked == DialogInterface.BUTTON_POSITIVE)
           } else {
               super.onDialogClosed(positiveResult)
           }
       }
    }
    
  2. 在 SettingsFragment 上覆盖 onDisplayPreferenceDialog

    override fun onDisplayPreferenceDialog(preference: Preference) {
        if (preference is ListPreference) {
            showListPreferenceDialog(preference)
        } else {
            super.onDisplayPreferenceDialog(preference)
        }
    }
    
    private void showListPreferenceDialog(ListPreference preference) {
        DialogFragment dialogFragment = new MaterialListPreference();
        Bundle bundle = new Bundle(1);
        bundle.putString("key", preference.getKey());
        dialogFragment.setArguments(bundle);
        dialogFragment.setTargetFragment(this, 0);
        dialogFragment.show(getParentFragmentManager(), "androidx.preference.PreferenceFragment.DIALOG");
    }
    
  3. 仅此而已。现在您将看到“您列出的材料”首选项。


0
投票

另一个解决方案(更彻底,但需要更少的代码更改)是从 https://github.com/androidx/androidx/tree/androidx-main/preference 创建首选项库的本地副本作为您的模块中的模块项目,然后修改类 PreferenceDialogFragmentCompat 以使用 MaterialAlertDialogBuilder。

© www.soinside.com 2019 - 2024. All rights reserved.