【问题标题】:Android: how to change the color of the datepicker divider?Android:如何更改日期选择器分隔线的颜色?
【发布时间】:2013-12-07 13:23:50
【问题描述】:

我的 Android 应用中有一个日期选择器,但现在我想将蓝色分隔线的颜色更改为绿色(请参见本文下方的图片)。 Stackoverflow 上有 some other discussions 谈论相同的内容,但没有一个给出导致解决方案的答案。

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

所以另一个选项应该是创建一个全新的自定义日期选择器。如果这使我能够改变分隔线的颜色,我很喜欢它。所以我在创建自定义日期选择器时查看了someofthetutorials,但它们似乎都没有定义分隔线的颜色。分隔线根本没有在 xml 文件或 java 文件中列出。

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

【问题讨论】:

标签: java android android-layout datepicker themes


【解决方案1】:

DatePickerDialog 中使用 android:datePickerMode="spinner" 更改颜色分隔线 => 为 DatePicker 设置 android:theme强>

日期选择器 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>

【讨论】:

    【解决方案2】:

    将主题设置为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"/>
    

    然后像这样在styles.xml 中定义NumberPickerStyle,指定colorControlNormal -

    <style name="NumberPickerStyle">
            <item name="colorControlNormal">@color/colorAccent</item>
    </style>
    

    【讨论】:

    • 我有完全相同的代码,但它不工作。它仍然是黑色的。但是我没有在对话框中使用 DatePicker。这只是我在对话框中显示的一个视图,我不知道这是否会改变任何内容。
    【解决方案3】:

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

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

    编辑 另一个library我也用过,它也很好,您可以在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>
    

    【讨论】:

    • 库因奇怪的异常而崩溃
    • CustomTimePicker 一种您可以 100% 自定义的方式。我使用它和工作魅力
    【解决方案4】:

    仅更改 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>
    

    【讨论】:

    • android:datePickerDialogTheme 用于 API >=21
    【解决方案5】:

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

    只需将其放入您的 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"
    

    并随心所欲地自定义它。

    【讨论】:

    • 在 Android 4.3 和 4.4 上不工作,在 android 5 及更高版本 - 工作得很好
    • 这不会改变 API 21 的分隔线颜色
    【解决方案6】:

    首先;维克拉姆,你做得很好,谢谢你的努力!我在net.simonvt.datepicker.DatePickerDialog 中缺少的一件事是设置我想与numberPickerDividerColor 匹配的titleDivider 颜色的选项。所以我在 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

    【讨论】:

      【解决方案7】:

      来自wreckerAndroid divider color DatePicker dialog

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

      <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.
                  />
      

      【讨论】:

        【解决方案8】:

        不幸的是,这不是一项简单的任务。

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

        我最近将 CalendarView 和 NumberPicker 向后移植到 API 8,主要是为了好玩。由于代码很容易获得(在 android 的源代码中查找 android.widget.NumberPicker 和其他代码),所有这些任务都需要时间,并且需要深入研究 android 的源代码。例子:

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

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

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

        无论如何,如果您决定编写 DatePicker 的自定义实现,您还必须为 NumberPicker 和 CalendarView(可选)编写它们。

        更简单的方法:

        Backported 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实际上来自LinearLayoutNumberPicker 继承此属性为 NumberPicker extends LinearLayout。但是这个divider 有不同的用途。传递给此属性的可绘制对象放置在LinearLayout 的子视图之间。

        android:showDividers 属性用于更改此分隔线的位置,可能的值是:

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

        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 反射的黑客式解决方法:

        这个答案here 给了我这个想法。我一般讨厌使用反射,主要是因为这个答案中列出的原因:Link。尽管为了完整起见我将其列在此处,但我建议您不要使用它。

        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();
                }
            }
        }
        

        我们在这里做什么:

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

        我使用的drawable可以从:here下载。

        【讨论】:

        • 可能的简化:npMonth = (NumberPicker) findViewById(Resources.getSystem().getIdentifier("month", "id", "android"));?
        • @Vikram 您是如何设法将日期的上下文本变为灰色的?使用TimePicker 对我来说所有文​​本颜色都是黑色的
        • @flexdroid 我不必将文本颜色设为灰色。通过查看源代码,NumberPicker 使用以下参数:TOP_AND_BOTTOM_FADING_EDGE_STRENGTH = 0.9f。由于缺少更好的词,这个值是使用覆盖方法getTopFadingEdgeStrength()getBottomFadingEdgeStrength() 应用于View 的特定部分的alpha。应用此 alpha 的特定部分在NumberPicker#initializeFadingEdges() 中确定。
        • @flexdroid 由于您没有看到此效果,请检查net.simonvt.numberpicker.NumberPicker.java 并确认TOP_AND_BOTTOM_FADING_EDGE_STRENGTH 确实设置为0.9f。您也可以尝试将此值更改为像0.1f 这样的戏剧性值。在这种情况下,顶部和底部的文本视图应该几乎不可见。
        • @Vikram TOP_AND_BOTTOM_FADING_EDGE_STRENGTH 设置为 0.9f 即使在更改值之后我也看不到效果。
        猜你喜欢
        • 1970-01-01
        • 2022-11-24
        • 1970-01-01
        • 1970-01-01
        • 2011-01-23
        • 1970-01-01
        • 2021-05-12
        • 2013-09-19
        • 1970-01-01
        相关资源
        最近更新 更多