【问题标题】:Difference between DialogPreference before and after AndroidXAndroidX 前后 DialogPreference 的区别
【发布时间】:2019-03-16 05:12:28
【问题描述】:

我们目前正在通过我们的 Android 应用项目迁移到 Androidx 命名空间。但是我注意到不仅名称空间似乎发生了变化。对于 DialogPreference,以前使用的一些接口现在也丢失了

例如,似乎缺少以下方法:onBindDialogView、showDialog、onDialogClosed。

由于我们使用其中一些方法来影响对话框的默认行为,我现在不清楚应该如何实现此功能。例如,我们在关闭对话框之前验证输入,我们将值保存在数据库中而不是 sharedpreferences 中,并向对话框添加一些动态元素。

有没有其他人已经遇到过这个问题并找到了解决方案?我错过了文档中的任何内容吗?我们可以/应该使用另一个概念吗?

可以使用 Fragments 代替 DialogPreference,但对于少量内容(例如,用户可以从中选择的树项目列表)这对我来说似乎是很多开销...

【问题讨论】:

    标签: android androidx


    【解决方案1】:

    您可以使用AlertDialog 编写自己的自定义Preference,而不是使用DialogPreference。 对于那些不想处理DialogPreferencePreferenceDialogFragmentCompat 的人来说,这可能是一种解决方法。

    import android.content.Context;
    import androidx.appcompat.app.AlertDialog;
    import androidx.preference.Preference;
    
    public class CustomDialogPreference extends Preference {
        private final Context context;
        public CustomDialogPreference(Context context, AttributeSet attrs) {
            super(context, attrs);
            this.context = context;
        }
        
        @Override
        protected void onClick() { //what happens when clicked on the preference
            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setTitle("TITLE")
                    .setMessage("message")
                    .setPositiveButton("OK", (dialog, which) -> {
                        String preferenceKey = getKey(); //You can update the SharedPreference with the key
                        //....
                   })
                    .setNegativeButton("CANCEL", (dialog, which) -> {
                        //....
                    })
                    .create().show();
        }
    }
    

    onClick()getKey() 方法属于 Preference 类。 context 对象自带构造函数等等..

    可以在 xml 文件中或以编程方式在 PreferenceFragment 中将键定义为其他首选项。

    <com.myApp.CustomDialogPreference
        android:key="my_preference_key"
        android:summary="..."
        android:title="..." />
    

    【讨论】:

      【解决方案2】:

      从 androidx 源文件开始,我将基于旧的 DialogPreference 的自定义类迁移到新的 androidx.preference.DialogPreference,过程如下:

      第一步

      基于旧版 DialogPreference 的旧自定义对话框类(例如 CustomDialogPreference)应拆分为两个单独的类:

      1. 一个类(例如 CustomPreference)应该扩展 androidx.preference.DialogPreference,并且只包含与首选项处理(数据管理)相关的代码。
      2. 另一个类(例如 CustomDialog)应该扩展 androidx.preference.PreferenceDialogFragmentCompat,并且只包含与对话框处理(用户界面)相关的代码,包括 onDialogClosed。此类应公开一个静态方法 newInstance 以返回此类的实例。

      第 2 步

      在基于 PreferenceFragmentCompat 的主要片段处理首选项中,应重写 onDisplayPreferenceDialog 方法以显示自定义对话框,例如:

          private static final String DIALOG_FRAGMENT_TAG = "CustomPreference";
      
          @Override
          public void onDisplayPreferenceDialog(Preference preference) {
              if (getParentFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) {
                  return;
              }
      
              if (preference instanceof CustomPreference) {
                  final DialogFragment f = CustomDialog.newInstance(preference.getKey());
                  f.setTargetFragment(this, 0);
                  f.show(getParentFragmentManager(), DIALOG_FRAGMENT_TAG);
              } else {
                  super.onDisplayPreferenceDialog(preference);
              }
          }
      

      【讨论】:

      • 和我做的一样。只是没时间写答案。非常感谢。
      • @little_planet 你能同时显示两个自定义类的内容吗?
      • 现代 AndroidX 也几乎 100% 正确:medium.com/@JakobUlbrich/…
      • 能否请所有者或@Livio 提供工作示例?我相信我们中的许多人都认为您的回答很有帮助,但无法使其发挥作用。
      • @Androidz 我成功地遵循了这个答案并迁移到 AndroidX ColorPicker 偏好,嵌入到我的“ToDo Agenda”中。现在可以了。请参阅此提交:github.com/andstatus/todoagenda/commit/…
      【解决方案3】:

      对于所有(像我一样)不完全理解我们应该如何结合androidx.preference.DialogPreferenceandroidx.preference.PreferenceDialogFragmentCompat 的人来说一点小技巧:

      第 1 步:

      在您的DialogFragmentonAttach() 方法中,获取您想要的SharedPreference 的值(从newInstance() 方法中获取密钥,或者将其硬核化)并将其保存为变量。另一方面,在关闭DialogFragment 之前将新值保存在SharedPreference。通过这样做,您已经创建了“自定义首选项”。

      第 2 步:

      创建空的androidx.preference.DialogPreference 并在您的PreferenceScreen 中使用它。然后将其与@Livio 第二步中所述的DialogFragment 结合起来:

      private static final String DIALOG_FRAGMENT_TAG = "CustomPreference";
      
      @Override
      public void onDisplayPreferenceDialog(Preference preference) {
          if (getFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) {
              return;
          }
      
          if (preference instanceof CustomPreference) {
              final DialogFragment f = CustomDialog.newInstance(preference.getKey());
              f.setTargetFragment(this, 0);
              f.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
          } else {
              super.onDisplayPreferenceDialog(preference);
          }
      }
      

      通过这样做,您将获得相同的结果,唯一的区别在于您需要在您的 DialogFragment 中自己处理 SharedPreference

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-11-03
        • 1970-01-01
        • 2016-02-24
        • 1970-01-01
        • 2013-07-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多