简体   繁体   English

Android分频器颜色DatePicker对话框

[英]Android divider color DatePicker dialog

I'm trying to change color of the blue dividers for a DatePicker in a dialog. 我正在尝试在对话框中更改DatePicker的蓝色分隔线的颜色。 This is just a normal DialogFragment with a DatePicker and a ButtonBar. 这只是一个带有DatePicker和ButtonBar的普通DialogFragment。

Does anyone know to change these dividers, or if it's even possible without replacing the entire DatePicker with a custom one? 有没有人知道改变这些分隔符,或者如果没有用自定义的替换整个DatePicker甚至可能?

截图DatePicker

Mini rant 迷你咆哮

Now I've seen too many answers suggesting the following code: 现在我看到太多的答案提示以下代码:

<style name="datePickerTheme" parent="@android:style/Widget.DeviceDefault.DatePicker">
    <item name="android:divider">**your @drawable/ or @color/ here**</item>
</style>

Which simply does not work. 这根本行不通。 Have you guys tried this before suggesting this code? 你们在建议这段代码之前试过这个吗? It should work perfectly, but it does not seem to work with the DatePicker. 应该可以正常工作,但它似乎不适用于DatePicker。

The following approach worked for me.This sets divider colours for all fields (also for am/pm) 以下方法适用于我。这为所有字段设置分隔颜色(也为am / pm)

 private void applyStyLing(TimePickerDialog timePickerDialog){
    Resources system = Resources.getSystem();
    int hourNumberPickerId = system.getIdentifier("hour", "id", "android");
    int minuteNumberPickerId = system.getIdentifier("minute", "id", "android");
    int ampmNumberPickerId = system.getIdentifier("amPm", "id", "android");

    NumberPicker hourNumberPicker = (NumberPicker) timePickerDialog.findViewById(hourNumberPickerId);
    NumberPicker minuteNumberPicker = (NumberPicker) timePickerDialog.findViewById(minuteNumberPickerId);
    NumberPicker ampmNumberPicker = (NumberPicker) timePickerDialog.findViewById(ampmNumberPickerId);

   setNumberPickerDividerColour(hourNumberPicker);
   setNumberPickerDividerColour(minuteNumberPicker);
   setNumberPickerDividerColour(ampmNumberPicker);
}

private void setNumberPickerDividerColour(NumberPicker number_picker){
    final int count = number_picker.getChildCount();

    for(int i = 0; i < count; i++){

        try{
            Field dividerField = number_picker.getClass().getDeclaredField("mSelectionDivider");
            dividerField.setAccessible(true);
                ColorDrawable colorDrawable = new ColorDrawable(mContext.getResources().getColor(R.color
                        .interactive_color));
            dividerField.set(number_picker,colorDrawable);

            number_picker.invalidate();
        }
        catch(NoSuchFieldException e){
            Log.w("setNumberPickerTxtClr", e);
        }
        catch(IllegalAccessException e){
            Log.w("setNumberPickerTxtClr", e);
        }
        catch(IllegalArgumentException e){
            Log.w("setNumberPickerTxtClr", e);
        }
    }
}

I solved this by doing this: 我通过这样做解决了这个问题:

I changed the DatePicker divider with reflection by finding the " mSelectionDivider ". 我通过查找“ mSelectionDivider ”来改变带反射DatePicker分隔符。 Then I had problems with the Title divider looking stupid, so i added a textview above the LinearLayout containing the 3 datepickers and used newFragment.setTitle(""); 然后我遇到了标题分割器看起来很愚蠢的问题,所以我在包含3个datepickersLinearLayout上面添加了一个textview并使用了newFragment.setTitle(""); to remove the original one. 删除原来的。

Example for divider drawable: Credits to the guy who made this! divider drawable的例子: 给这个人的信誉! :) http://ge.tt/8wK7TZ71/v/0?c :) http://ge.tt/8wK7TZ71/v/0?c

Result picture <-My result 结果图片 < - 我的结果

Example: 例:

    public DatePickerDialog makeDatePicker(OnDateSetListener listener, Calendar cal) {
    Calendar c;
    if (cal == null) {
        c = Calendar.getInstance();
    } else {
        c = cal;
    }
    int year = c.get(Calendar.YEAR);
    int month = c.get(Calendar.MONTH);
    int day = c.get(Calendar.DAY_OF_MONTH);
    DatePickerDialog newFragment = new DatePickerDialog(this, listener, year, month, day);

    // removes the original topbar:
    newFragment.setTitle(""); 

    // Divider changing:
    DatePicker dpView = newFragment.getDatePicker(); 
    LinearLayout llFirst = (LinearLayout) dpView.getChildAt(0);
    LinearLayout llSecond = (LinearLayout) llFirst.getChildAt(0);
    for (int i = 0; i < llSecond.getChildCount(); i++) {
        NumberPicker picker = (NumberPicker) llSecond.getChildAt(i); // Numberpickers in llSecond
        // reflection - picker.setDividerDrawable(divider); << didn't seem to work.
        Field[] pickerFields = NumberPicker.class.getDeclaredFields();
        for (Field pf : pickerFields) {
            if (pf.getName().equals("mSelectionDivider")) {
                pf.setAccessible(true);
                try {
                    pf.set(picker, getResources().getDrawable(R.drawable.np_numberpicker_selection_divider_orange));
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (NotFoundException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                break;
            }
        }
    }
    // New top:
    int titleHeight = 90;
    // Container:
    LinearLayout llTitleBar = new LinearLayout(this);
    llTitleBar.setOrientation(LinearLayout.VERTICAL);
    llTitleBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, titleHeight));

    // TextView Title:
    TextView tvTitle = new TextView(this);
    tvTitle.setText("Select a date");
    tvTitle.setGravity(Gravity.CENTER);
    tvTitle.setPadding(10, 10, 10, 10);
    tvTitle.setTextSize(24);
    tvTitle.setTextColor(Color.BLACK);
    tvTitle.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, titleHeight-2));
    llTitleBar.addView(tvTitle);

    // View line:
    View vTitleDivider = new View(this);
    vTitleDivider.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 2));
    vTitleDivider.setBackgroundColor(getResources().getColor(R.color.crumblrOrange));
    llTitleBar.addView(vTitleDivider);

    dpView.addView(llTitleBar);
    FrameLayout.LayoutParams lp = (android.widget.FrameLayout.LayoutParams) llFirst.getLayoutParams();
    lp.setMargins(0, titleHeight, 0, 0);
    return newFragment;
}

I based this code on Ajit's answer , but I tweaked it for DatePicker rather than TimePicker . 我将此代码基于Ajit的答案 ,但我将其调整为DatePicker而不是TimePicker Moreover, I added a null check just to stay on the safe side: 此外,为了保持安全,我添加了一个null检查:

public static void colorizeDatePicker(DatePicker datePicker) {
    Resources system = Resources.getSystem();
    int dayId = system.getIdentifier("day", "id", "android");
    int monthId = system.getIdentifier("month", "id", "android");
    int yearId = system.getIdentifier("year", "id", "android");

    NumberPicker dayPicker = (NumberPicker) datePicker.findViewById(dayId);
    NumberPicker monthPicker = (NumberPicker) datePicker.findViewById(monthId);
    NumberPicker yearPicker = (NumberPicker) datePicker.findViewById(yearId);

    setDividerColor(dayPicker);
    setDividerColor(monthPicker);
    setDividerColor(yearPicker);
}

private static void setDividerColor(NumberPicker picker) {
    if (picker == null)
        return;

    final int count = picker.getChildCount();
    for (int i = 0; i < count; i++) {
        try {
            Field dividerField = picker.getClass().getDeclaredField("mSelectionDivider");
            dividerField.setAccessible(true);
            ColorDrawable colorDrawable = new ColorDrawable(picker.getResources().getColor(R.color.colorAccent));
            dividerField.set(picker, colorDrawable);
            picker.invalidate();
        } catch (Exception e) {
            Log.w("setDividerColor", e);
        }
    }
}

Output 产量

彩色分隔线

This fixed my problem adding below line of code to App theme style. 这解决了我的问题,将下面的代码行添加到App主题样式。

<item name="colorControlNormal">@color/colorAccent</item>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
  <item name="colorControlNormal">@color/blue</item> 
</style>

Take into account: 考虑到:

You don't need a new R.drawable.divider 您不需要新的R.drawable.divider

you can write: 你可以写:

 pf.set(number_picker, new ColorDrawable(getResources().getColor(R.color.red)));

This version is adjusted for specific use with DatePicker . 此版本已针对DatePicker的特定用途进行了调整。 While Andrea Lazzarotto's version works fine, it uses an unnecessary loop which leads to multiple appliance of the color change. 虽然Andrea Lazzarotto的版本运行良好,但它使用了一个不必要的循环,这导致了多种颜色变化的应用。 Besides minor code improvements, my version uses the app theme's primary color to match the divider color (see How can I get the primary color from my app theme? ). 除了小的代码改进,我的版本使用应用程序主题的主要颜色来匹配分隔符颜色(请参阅如何从我的应用程序主题获取主要颜色? )。 Tested with Android 6.0 and 8.0: 使用Android 6.0和8.0进行测试:

private void colorizeDatePicker(final DatePicker datePicker) {
    final Resources system = Resources.getSystem();
    final String defType = "id";
    final String defPackage = "android";

    final int dayId = system.getIdentifier("day", defType, defPackage);
    final int monthId = system.getIdentifier("month", defType, defPackage);
    final int yearId = system.getIdentifier("year", defType, defPackage);

    final NumberPicker dayPicker = (NumberPicker) datePicker.findViewById(dayId);
    final NumberPicker monthPicker = (NumberPicker) datePicker.findViewById(monthId);
    final NumberPicker yearPicker = (NumberPicker) datePicker.findViewById(yearId);

    setDividerColor(dayPicker);
    setDividerColor(monthPicker);
    setDividerColor(yearPicker);
}

private void setDividerColor(final NumberPicker picker) {
    if (picker == null) {
        return;
    }

    try {
        final Field dividerField = picker.getClass().getDeclaredField("mSelectionDivider");
        dividerField.setAccessible(true);

        final TypedValue outValue = new TypedValue();
        getContext().getTheme().resolveAttribute(R.attr.colorPrimary, outValue, true);
        final int dividerColor = outValue.data;

        dividerField.set(picker, new ColorDrawable(dividerColor));
        picker.invalidate();
    } catch (Exception e) {
    }
}

Yes of course you can. 是的,你当然可以。 You can use these attributes for instance: 您可以使用以下属性:

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

Update : 更新:

You can use this custom datepicker . 您可以使用此自定义日期选择器 It's highly customizable and backward competiable. 它具有高度可定制性和向后竞争力。 It basically uses numberpicker and you can set divider using attributes above. 它基本上使用numberpicker,你可以使用上面的属性设置divider。

Thanks Mvj for solving the problem! 感谢Mvj解决问题! Just thought I'd also show my implementation of your solution on the timepickers' dividers. 我想我也会在时间戳的分频器上显示我的解决方案。

    TimePickerDialog ptd = new TimePickerDialog(getActivity(), R.style.PickerStyler, this, hour, minute,DateFormat.is24HourFormat(getActivity()));
    ptd.setTitle("");

    //Needs to be try catched
    Field mTimePickerField = ptd.getClass().getDeclaredField("mTimePicker");
    mTimePickerField.setAccessible(true);
    TimePicker mTimePickerInstance = (TimePicker) mTimePickerField.get(ptd);    

    LinearLayout llFirst = (LinearLayout) mTimePickerInstance.getChildAt(0);
    LinearLayout llSecond = (LinearLayout) llFirst.getChildAt(0);
    boolean continiue = false;
    NumberPicker picker = null;
    for (int i = 0; i < llSecond.getChildCount(); i++) {            
        continiue = true;
        try{picker = (NumberPicker) llSecond.getChildAt(i);
            }catch(Exception e){continiue = false;}

        if(continiue){
            Field[] pickerFields = NumberPicker.class.getDeclaredFields();
            for (Field pf : pickerFields) {
                if (pf.getName().equals("mSelectionDivider")) {
                    pf.setAccessible(true);
                    try {
                        pf.set(picker, getResources().getDrawable(R.drawable.divider));
                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    } catch (NotFoundException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    break;
                }
            }
        }
    }   

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM