it-swarm.com.ru

Android: как изменить цвет делителя даты?

В моем приложении для Android есть средство выбора даты, но теперь я хочу изменить цвет синих разделителей на зеленый (см. Изображение под этим текстом). В Stackoverflow есть некоторыедругиеобсуждения , которые говорят об одном и том же, но ни один из них не дает ответа, который приводит к решению.

Поэтому я отправился на поиски себя и обнаружил, что на самом деле есть Android: datePickerStyle, а также есть Android: разделитель. Однако я не знаю, относится ли разделитель к разделителю в указателе даты вообще. Я перепробовал множество комбинаций из двух, но мне кажется, что он не работает. Итак, мой первый вопрос: Соответствует ли разделитель Android: разделитель в указателе даты, и как я могу использовать его для изменения цвета?

Таким образом, другой вариант должен создать полностью новый пользовательский указатель даты. Если это позволяет мне просто изменить цвет разделителя, я за это. Итак, я взглянул на некоторыеofthetutorials при создании пользовательского средства выбора даты, но ни один из них, похоже, не определяет цвет делители. Разделители просто не перечислены в файлах xml или в файлах Java.

Было бы замечательно, если бы существовал какой-то шаблонный код для воссоздания средства выбора даты, как он отображается в данный момент, включая код, который устанавливает цвет разделителей. Надеюсь, это позволило бы мне скопировать его и просто изменить настройки цвета разделителя где-нибудь. Итак, мой второй вопрос: Кто-нибудь знает какой-нибудь шаблонный код, который просто реализует средство выбора даты, как оно есть сейчас (включая определение разделителей)?

enter image description here

35
kramer65

К сожалению, это не тривиальная задача.

DatePickers использовать виджеты NumberPicker и CalendarView внутри. Например, опубликованное вами изображение использует 3 NumberPickers. А разделители, о которых вы говорите, происходят из атрибута NumberPicker: selectionDivider. Проблема заключается в том, что этот атрибут не является общедоступным и не является numberPickerStyle, с помощью которого этот атрибут устанавливается. 

Недавно я перенес обратно CalendarView и NumberPicker в API 8, в основном для развлечения. Поскольку код легко доступен (ищите Android.widget.NumberPicker и другие в исходном коде Android), все, что нужно для этой задачи, - это время, а некоторые копаются в исходном коде Android. Примеры:

  1. Легко ==> Вам придется изменить приватную переменную из класса View на их методы доступа

    mLeft (защищенная переменная в классе View) ==> getLeft () (публичный метод доступа)

  2. Наиболее трудоемкой задачей было восстановление методов доступности.

В любом случае, если вы решите написать собственную реализацию DatePicker, вам придется написать их также для NumberPicker и CalendarView (опционально).

Более простой способ:

BackPorted DatePicker доступен в виде библиотеки здесь: Android-DatePicker . Как упоминалось выше, вы будете использовать backported CalendarView и NumberPicker в сочетании с этим DatePicker.

Что нужно изменить:

Используйте {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>

И это все.

Вывод с использованием библиотек:

enter image description here

Правка:

Относится ли 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:

Этот ответ здесь дал мне идею. Я ненавижу использовать повторение в целом, главным образом по причинам, перечисленным в этом ответе: Ссылка . Хотя я приведу это здесь для полноты картины, я предлагаю вы его не используете.

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
  • Если вы откроете date_picker.xml в sdk/platforms/Android-xx/res/layout, вы увидите, что три NumberPickers имеют идентификаторы month, day, year. Мы получаем доступ к Android.internal.R.id, чтобы получить идентификаторы ресурсов для этих NumberPickers.
  • Мы создаем три объекта NumberPicker, используя эти идентификаторы с методом findViewById(int).
  • Затем получите доступ к полю mSelectionDivider и получите его, используя функцию relection.
  • Установите поле в доступное (как его объявленное окончание), установите его значение, используя метод Field#set(Object, Object). Первый аргумент - это Объект, с которым мы выполняем эту операцию. Второй аргумент - это Объект, который мы хотим установить.

Используемый мной чертеж можно скачать с: здесь .

100
Vikram

Я думаю, что самым простым решением, вероятно, является использование стилей.

Просто поместите это в ваш документ 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"

и настроить его так, как вам нравится.

22
JCLaHoot

Есть одна библиотека у них есть настройка времени и даты. Вы можете изменить цвет разделителя следующим образом

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

Edit Другая библиотека Я также использовал эту функцию, которая также хороша тем, что вы можете настроить ее следующим образом в 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>
3
Rajesh Nasit

Установка темы на макет 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"/>

а затем определите NumberPickerStyle в styles.xml, указав colorControlNormal следующим образом:

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

Прежде всего; Викрам, вы проделали отличную работу, спасибо за ваши усилия! Единственное, чего мне не хватало в 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

0
GMan

Чтобы изменить только цвет делителя в DatePickerDialog, достаточно изменить Android: datePickerDialogТем в вашей теме: 

Стиль темы:

 <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>
0
Wiktor Wardzichowski