Android:如何更改日期选择器分隔线的颜色?

IT小君   2021-09-26T03:00:11

我的 Android 应用程序中有一个日期选择器,但现在我想将蓝色分隔线的颜色更改为绿色(请参阅本文下方的图片)。在 Stackoverflow 上还有一些 其他 讨论也讨论了同样的问题,但没有一个给出导致解决方案的答案。

所以我自己去找,发现实际上有一个 android:datePickerStyle,还有一个 android:divider。但是,我不知道分隔符是否实际上是指日期选择器中的分隔符。我尝试了两者的多种组合,但我似乎没有让它起作用。所以我的第一个问题:android:divider 是否指的是日期选择器中的分隔符,我如何使用它来改变颜色?

所以另一个选项应该是创建一个全新的自定义日期选择器。如果这让我能够改变分隔线的颜色,我会为之倾倒。因此,我不得不看看一些 教程创建自定义日期选择器,但他们都不来定义分隔的颜色。分隔符根本没有在 xml 文件或 java 文件中列出。

如果有某种样板代码来重新创建当前显示的日期选择器,包括设置分隔线颜色的代码,那就太好了。希望这能让我复制它并简单地在某处更改分隔线的颜色设置。所以我的第二个问题:有人知道任何简单地实现日期选择器的样板代码吗(包括分隔符的定义)?

在此处输入图片说明

评论(8)
IT小君

不幸的是,这不是一项微不足道的任务。

DatePickers使用小部件NumberPickerCalendarView内部。例如,您发布的图片使用的是 3 NumberPickers你所说的分隔符来自 NumberPicker 的属性:selectionDivider问题是这个属性不是公开的,也不是numberPickerStyle,通过它来设置这个属性。

我最近将 CalendarView 和 NumberPicker 向后移植到 API 8,主要是为了好玩。由于代码随时可用(android.widget.NumberPicker在 android 的源代码中查找和其他代码),所有这些任务都需要时间,以及一些挖掘 android 源代码的工作。例子:

  1. 简单 ==> 您必须将私有变量从 View 类更改为它们的访问器方法

    mLeft(View 类中的受保护变量)==> getLeft()(公共访问器方法)

  2. 最耗时的任务是恢复辅助功能方法。

在任何情况下,如果您决定编写 DatePicker 的自定义实现,则还必须为 NumberPicker 和 CalendarView(可选)编写它们。

更简单的方法:

向后移植的 DatePicker 可在此处用作库:Android-DatePicker如上所述,您将与此 DatePicker 结合使用反向移植的CalendarViewNumberPicker

你需要改变的:

使用{library-numberpicker} / res / drawable-xxxx / np_numberpicker_selection_divider.9.png作为模板,并改变“蓝色”的颜色为绿色(我用的Pixlr)。如果您想完全使用蓝色分隔线,您可以使用相同的名称保存它,或者使用不同的名称并在{library-numberpicker} / res / values / themes.xml.

themes.xml如果您选择不同的名称所需的更改

<style name="NPWidget.Holo.NumberPicker" parent="NPWidget.NumberPicker">
    ....
    <item name="selectionDivider">@drawable/new_nine_path_drawable_name</item>
    ....
</style>

就是这样。

使用库输出:

在此处输入图片说明

编辑:

是否android:divider指的是日期选择器中的分隔符,我如何使用它来改变颜色?

该属性divider实际上来自LinearLayout. NumberPicker将此属性继承为NumberPicker extends LinearLayout. 但这divider有不同的目的。传递给此属性的可绘制对象放置在 的子视图之间LinearLayout

该属性android:showDividers用于更改此分隔符的位置,可能的值为:

  • none:没有显示分隔线
  • 开始:分隔线显示在第一个子视图之前
  • 中间:分隔线显示在每个子视图之后,而不是在最后一个子视图之后
  • 结束:分隔线显示在最后一个子视图之后

该属性android:dividerPadding是不言自明的。

即使 NumberPicker 继承了这个属性,它也不使用它。这从您自己的研究和试验中可以明显看出:I tried a multitude of combinations of the two, but I don't seem to get it to work.

要查看操作中的分隔线属性:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:divider="@android:drawable/ic_media_play"
    android:showDividers="middle" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="World," />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Again" />

</LinearLayout>

使用 Java 反射的 Hack-ish 解决方法:

这个答案在这里给了我这个想法。我一般讨厌使用反射,主要是出于此答案中列出的原因:链接虽然我在这里列出它是为了完整起见,但我建议您不要使用它。

public class CDP extends android.widget.DatePicker {

    public CDP(Context context, AttributeSet attrs) {
        super(context, attrs);

        Class<?> internalRID = null;
        try {
            internalRID = Class.forName("com.android.internal.R$id");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        Field month = null;
        try {
            month = internalRID.getField("month");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }

        NumberPicker npMonth = null;
        try {
            npMonth = (NumberPicker) findViewById(month.getInt(null));
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        Field day = null;
        try {
            day = internalRID.getField("day");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }

        NumberPicker npDay = null;
        try {
            npDay = (NumberPicker) findViewById(day.getInt(null));
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        Field year = null;
        try {
            year = internalRID.getField("year");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }

        NumberPicker npYear = null;
        try {
            npYear = (NumberPicker) findViewById(year.getInt(null));
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        Class<?> numberPickerClass = null;
        try {
            numberPickerClass = Class.forName("android.widget.NumberPicker");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        Field selectionDivider = null;
        try {
            selectionDivider = numberPickerClass.getDeclaredField("mSelectionDivider");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }

        try {
            selectionDivider.setAccessible(true);
            selectionDivider.set(npMonth, getResources().getDrawable(
                       R.drawable.np_numberpicker_selection_divider_green));
            selectionDivider.set(npDay, getResources().getDrawable(
                       R.drawable.np_numberpicker_selection_divider_green));
            selectionDivider.set(npYear, getResources().getDrawable(
                       R.drawable.np_numberpicker_selection_divider_green));
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (NotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

我们在这里做什么:

  • 扩展日期选择器
  • 如果你打开date_picker.xmlsdk/platforms/android-xx/res/layout,你会看到这三个NumberPickers有ID monthdayyear我们可以android.internal.R.id获取这些 NumberPicker 的资源 ID。
  • 我们使用这些 id 和findViewById(int)方法创建了三个 NumberPicker 对象
  • 然后,使用重选访问和检索字段mSelectionDivider
  • 将字段设置为可访问(作为其声明的最终版本),使用Field#set(Object, Object)方法设置其值第一个参数是我们执行此操作的对象。第二个参数是我们要设置的对象。

我用过的 drawable 可以从这里下载

2021-09-26T03:00:11   回复
IT小君

我认为最简单的解决方案可能是使用样式。

把它放在你的styles.xml 文件中

    <!-- changes the default colours for EditTexts, including non-text elements (also works with the DatePicker -->

<style name="appCompatStyle" parent="Theme.AppCompat.Light">
    <item name="colorControlNormal">@color/lightPrimaryText</item>
    <item name="colorControlActivated">@color/colorAccent</item>
    <item name="android:editTextStyle">@style/editTextStyle</item>
</style>


<!-- changes the default text colour for the EditTexts -->
<style name="editTextStyle" parent="android:style/Widget.EditText">
    <item name="android:textColor">@color/lightPrimaryText</item>
</style>

并将这些属性放在您的布局 XML 中

android:theme="@style/appCompatStyle"

并根据您的喜好自定义它。

2021-09-26T03:00:11   回复
IT小君

将主题设置为DatePicker布局并添加colorControlNormal到它对我有用。

在您的布局的 xml 中添加一个DatePicker应用主题,如下所示 -

<DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
            android:theme="@style/NumberPickerStyle"
            android:datePickerMode="spinner"
            android:calendarViewShown="false"
            android:layout_gravity="center_horizontal"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"/>

然后像这样定义NumberPickerStyleinstyles.xml指定colorControlNormal-

<style name="NumberPickerStyle">
        <item name="colorControlNormal">@color/colorAccent</item>
</style>
2021-09-26T03:00:12   回复
IT小君

他们有一个库,他们有自定义时间和日期选择器。因为您可以按照以下方式更改分隔线的颜色

    timePicker.setSelectionDivider(new ColorDrawable(0xffff0000));
    timePicker.setSelectionDividerHeight(2);

编辑 另一个我也使用过的,它也很好,您可以在 thems.xml 中使用以下方式进行自定义

<style name="NPWidget.Holo.NumberPicker" parent="NPWidget.NumberPicker">
        <item name="solidColor">@android:color/transparent</item>
        <item name="selectionDivider">@color/div_color</item>
        <item name="selectionDividerHeight">0.3dip</item>
        <item name="internalLayout">@layout/number_picker_with_selector_wheel</item>
        <item name="internalMinWidth">64dip</item>
        <item name="internalMaxHeight">140dip</item>
        <item name="virtualButtonPressedDrawable">@drawable/item_background_holo_dark</item>
    </style>
2021-09-26T03:00:12   回复
IT小君

使用android:datePickerMode="spinner" =>DatePicker设置android:theme更改DatePickerDialog 中的分色器

日期选择器 Xml:

<DatePicker
        android:id="@+id/datePicker"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:calendarViewShown="false"
        android:theme="@style/MyAppTheme.DatePicker"
        android:datePickerMode="spinner" />

MyAppTheme Xml:

<style name="MyAppTheme.DatePicker" parent="AppTheme">
    <item name="colorControlNormal"> ?colorAccent </item>
</style>

截屏

2021-09-26T03:00:12   回复
IT小君

首先; 维克拉姆,你做得很好,谢谢你的努力!我缺少的一件事是net.simonvt.datepicker.DatePickerDialog设置titleDivider我想要匹配颜色的选项numberPickerDividerColor所以我在 Vikrams 实现中添加了这个选项,并在这里发布。这是与更改AlertDialog.titleDividerColor. 也许它会帮助某人。

class net.simonvt.datepicker.DatePickerDialog
private int titleDividerColor;

显示对话框时设置颜色很重要,所以我在onAttachedToWindow方法中这样做

@Override
public void onAttachedToWindow() {
    super.onAttachedToWindow();

    if (titleDividerColor <= 0) { return; }

    try {
        int dividerId = getContext().getResources().getIdentifier("android:id/titleDivider", null, null);
        View divider = findViewById(dividerId);
        if (divider != null) {
            divider.setBackgroundColor(getContext().getResources().getColor(titleDividerColor));
        }
    } catch (Exception e) {}
}

public void setTitleDividerColor(int titleDividerColor) {
    this.titleDividerColor = titleDividerColor;
}

public int getTitleDividerColor() {
    return titleDividerColor;
}

编辑

我在这里发布了另一个解决方案https://stackoverflow.com/a/33800696/1134335

2021-09-26T03:00:12   回复
IT小君

对于更改 DatePickerDialog 中的分隔线颜色,更改主题中的 android:datePickerDialogTheme 样式就足够了:

主题风格:

 <style name="BaseTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:datePickerDialogTheme">@style/style_date_picker_dialog</item>
</style>

对话风格:

<style name="style_date_picker_dialog" parent="AppCompatAlertDialogStyle">
<item name="colorControlNormal">@color/colorAccent</item>
</style>
2021-09-26T03:00:13   回复
IT小君

清障车Android的分隔颜色的DatePicker对话框

例如,您可以使用这些属性:

<NumberPicker
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            selectionDivider="@color/black" //The divider for making the selection area
            selectionDividerHeight="1px"//The height of the selection divider
            selectionDividersDistance="3dp"//The distance between the two selection dividers
            internalLayout="@layout/something"//The layout of the number picker.
            internalMaxHeight="5dp"//The max height of the NumberPicker (also check other variations)
            internalMinWidth="5dp" // The max width of the NumberPicker (also check other variations)
            virtualButtonPressedDrawable="@drawable/something"//The drawable for pressed virtual (increment/decrement) buttons.
            />
2021-09-26T03:00:13   回复