当前位置: 首页 > 知识库问答 >
问题:

Android 7牛轧糖上的DatePickerDialog全息造型失败

梅修贤
2023-03-14

根据我们的客户需求,我们希望在所有Android操作系统版本的DatePickerDialog上保持全息样式,比如:Android 7上的DatePicker-

但在Android 7上似乎不能正常工作:

Android 7上的DatePicker

new DatePickerDialog(getContext(), AlertDialog.THEME_HOLO_LIGHT,
                        mCalendarPickerListener,
                        calendar.get(Calendar.YEAR),
                        calendar.get(Calendar.MONTH),
                        calendar.get(Calendar.DAY_OF_MONTH));

共有1个答案

融修平
2023-03-14

我使用DatePickerDialog提示用户生日。不幸的是,当我尝试时,我收到了许多用户对材料主题对话框的投诉,所以切换到它对我来说不是一个选择:我必须坚持全息主题对话框。

事实证明,Android7.0附带了一个bug:试图在这个平台上使用Holo主题,却回到了为DatePickerDialog使用一个破碎的材料主题。请参见以下两个bug报告:

  • 第222808期
  • 第222208期

我使用了Jeff Lockhart在这些bug报告中引用的改进形式:

private static final class FixedHoloDatePickerDialog extends DatePickerDialog {
    private FixedHoloDatePickerDialog(Context context, OnDateSetListener callBack,
                                      int year, int monthOfYear, int dayOfMonth) {
        super(context, callBack, year, monthOfYear, dayOfMonth);

        // Force spinners on Android 7.0 only (SDK 24).
        // Note: I'm using a naked SDK value of 24 here, because I'm
        // targeting SDK 23, and Build.VERSION_CODES.N is not available yet.
        // But if you target SDK >= 24, you should have it.
        if (Build.VERSION.SDK_INT == 24) {
            try {
                final Field field = this.findField(
                        DatePickerDialog.class,
                        DatePicker.class,
                        "mDatePicker"
                );

                final DatePicker datePicker = (DatePicker) field.get(this);
                final Class<?> delegateClass = Class.forName(
                        "android.widget.DatePicker$DatePickerDelegate"
                );
                final Field delegateField = this.findField(
                        DatePicker.class,
                        delegateClass,
                        "mDelegate"
                );

                final Object delegate = delegateField.get(datePicker);
                final Class<?> spinnerDelegateClass = Class.forName(
                        "android.widget.DatePickerSpinnerDelegate"
                );

                if (delegate.getClass() != spinnerDelegateClass) {
                    delegateField.set(datePicker, null);
                    datePicker.removeAllViews();

                    final Constructor spinnerDelegateConstructor =
                            spinnerDelegateClass.getDeclaredConstructor(
                                    DatePicker.class,
                                    Context.class,
                                    AttributeSet.class,
                                    int.class,
                                    int.class
                            );
                    spinnerDelegateConstructor.setAccessible(true);

                    final Object spinnerDelegate = spinnerDelegateConstructor.newInstance(
                            datePicker,
                            context,
                            null,
                            android.R.attr.datePickerStyle,
                            0
                    );
                    delegateField.set(datePicker, spinnerDelegate);

                    datePicker.init(year, monthOfYear, dayOfMonth, this);
                    datePicker.setCalendarViewShown(false);
                    datePicker.setSpinnersShown(true);
                }
            } catch (Exception e) { /* Do nothing */ }
        }
    }

    /**
     * Find Field with expectedName in objectClass. If not found, find first occurrence of
     * target fieldClass in objectClass.
     */
    private Field findField(Class objectClass, Class fieldClass, String expectedName) {
        try {
            final Field field = objectClass.getDeclaredField(expectedName);
            field.setAccessible(true);
            return field;
        } catch (NoSuchFieldException e) { /* Ignore */ }

        // Search for it if it wasn't found under the expectedName.
        for (final Field field : objectClass.getDeclaredFields()) {
            if (field.getType() == fieldClass) {
                field.setAccessible(true);
                return field;
            }
        }

        return null;
    }
}

它所做的是:

  • 获取属于此对话框的私有datepicker mdatepicker字段
  • 获取属于此对话框的私有DatePickerDelegate MDelegate字段
  • 检查委托是否已经是DatePickerSpinnerDelegate的实例(我们需要的委托类型)
  • DatePicker中删除所有视图,因为它们是材料日历小部件
  • 创建datepickerspinnerdelegate的新实例,并将其分配给此对话框的mdatepickermdelegate字段
  • 使用日历信息和一些参数重新初始化MDatePicker,以使其膨胀旋转器
final Context themedContext = new ContextThemeWrapper(
        this.getContext(),
        android.R.style.Theme_Holo_Light_Dialog
);

final DatePickerDialog dialog = new FixedHoloDatePickerDialog(
        themedContext,
        datePickerListener,
        calender.get(Calendar.YEAR),
        calendar.get(Calendar.MONTH),
        calendar.get(Calendar.DAY_OF_MONTH)
);
    null
 类似资料:
  • 例外 片段点击:- 在活动中, 详细活动清单, 图像加载使用毕加索, 模型类 从活动到片段的数据流, 我尝试过的解决方案 注意:-应用程序崩溃只在NOUGAT 最后,我实现了修复 将targetSdkVersion从25更改为23 更改后,我的应用程序在牛轧糖也不会崩溃。 我所要知道的就是这个合适的解决方案,或者有什么变通办法。 请引导到正确的方式。 提前谢谢。 碎片 选项卡布局 列表视图

  • 我的应用程序在之前的Android版本上运行完美,在实际设备上从4.0测试到6.0.1。工作室仿真牛轧糖7.0和7.1没问题。然而,当我让我的朋友在他运行7.0的设备上测试APK时,这在几秒钟内就发生了: 崩溃通知 我没有访问该设备的权限(他住得很远),并且我无法在网上找到该特定错误的任何相关信息。原因可能是什么?

  • 我尝试了太多的选项/博客/脚本来安装GooglePlay for Emulator(通过Android Studio运行),但都没有成功。我看到了很多不同的错误 失败[安装失败\u更新不兼容] 评论-为什么在Emulator上安装GooglePlay如此困难,有人能提供与Marshmallow/Noughat一起使用的步骤或GAPP吗。或者为什么谷歌不提供标准步骤来为模拟器安装GApps! 以下是

  • 在清单文件中:

  • 我正在使用reverfit进行api调用,我从服务器得到了几乎不到30KB大小的JSON响应。当JSON将响应解析为一个复杂对象时,它会抛出这个错误。 如果我尝试将响应存储在对象类中,然后通过LinkedHashMap获取值,我就能够获取数据。但是,这将是一个繁琐的过程。 有谁能帮我弄清楚这里的问题是什么,以及如何找到解决办法吗? 根据我的研究,这种情况只发生在版本>=牛轧糖的android设备上