Подтвердить что ты не робот

Изменение цвета разделителя NumberPicker

В последних версиях Android, подборщики чисел используют синий разделитель при рисовании (см. изображение ниже).

enter image description here

Я хотел бы изменить этот цвет. Есть ли рабочее решение? или, возможно, библиотеку, в которой установлена ​​обновленная версия NumberPicker, которая позволяет настроить цвет разделителя?

Я пробовал android-numberpicker, но я получил ошибку (см. ниже) во время выполнения из-за некоторого кода из библиотеки, которая пытается получить доступ к идентификатору ресурса, который не существует.

android.content.res.Resources$NotFoundException: Resource ID #0x0
        at android.content.res.Resources.getValue(Resources.java:1123)
        at android.content.res.Resources.loadXmlResourceParser(Resources.java:2309)
        at android.content.res.Resources.getLayout(Resources.java:939)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:395)
        at net.simonvt.numberpicker.NumberPicker.<init>(NumberPicker.java:635)
        at net.simonvt.numberpicker.NumberPicker.<init>(NumberPicker.java:560)
        at net.simonvt.numberpicker.NumberPicker.<init>(NumberPicker.java:550)
4b9b3361

Ответ 1

Исходя из этого (fooobar.com/questions/165510/..., хотя это касается DatePicker) существует несколько способов:

  • Напишите свой собственный номерной номер без mSelectionDivider и его веток или используйте backported Vikram. В последнем случае:

    • скачать из lib из github
    • изменить drawable в res/drawable-xxx/np_numberpicker_selection_divider.9.png:

      • для прозрачного (или любого другого).9.png
      • создайте ресурс строки формы np_numberpicker_selection_divider.xml в res/drawable (с ростом 0dp или прозрачным цветом).
    • ИЛИ удалите ветвь if (mSelectionDivider != null) из метода onDraw (Canvas) в NumberPicker.java, например здесь

  • Используйте отражение для доступа private final field mSelectionDivider (подробности: https://github.com/android/platform_frameworks_base/blob/master/core/java/android/widget/NumberPicker.java) - например. см. модификацию здесь. Я использовал отражение, но это не лучшее решение.

Ответ 2

Если вы хотите просто изменить цвет (на основе ответа на stannums):

private void setDividerColor(NumberPicker picker, int color) {

    java.lang.reflect.Field[] pickerFields = NumberPicker.class.getDeclaredFields();
    for (java.lang.reflect.Field pf : pickerFields) {
        if (pf.getName().equals("mSelectionDivider")) {
            pf.setAccessible(true);
            try {
                ColorDrawable colorDrawable = new ColorDrawable(color);
                pf.set(picker, colorDrawable);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (Resources.NotFoundException e) {
                e.printStackTrace();
            }
            catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            break;
        }
    }
}

И после этого

setDividerColor(mNumberPicker, Color.GREEN);

Ответ 3

Это работало для меня без использования отражения.

my_layout.xml

<NumberPicker
   ...
   android:theme="@style/DefaultNumberPickerTheme" />

Styles.xml(AppTheme - это тема моего приложения в приложении)

<style name="DefaultNumberPickerTheme" parent="AppTheme">
        <item name="colorControlNormal">@color/dividerColor</item>
</style>

Ответ 4

Я использую обходной метод Java:

  private void setDividerColor (NumberPicker picker) {   

        java.lang.reflect.Field[] pickerFields = NumberPicker.class.getDeclaredFields();
        for (java.lang.reflect.Field pf : pickerFields) {
            if (pf.getName().equals("mSelectionDivider")) {
                pf.setAccessible(true);
                try {
                    //pf.set(picker, getResources().getColor(R.color.my_orange));
                    //Log.v(TAG,"here");
                    pf.set(picker, getResources().getDrawable(R.drawable.dot_orange));
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (NotFoundException e) {
                    e.printStackTrace();
                } 
                catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                break;
            }
        }
        //}
     }

или метод Котлина:

private fun NumberPicker.setDividerColor(color: Int) {
    val dividerField = NumberPicker::class.java.declaredFields.firstOrNull { it.name == "mSelectionDivider" } ?: return
    try {
       dividerField.isAccessible = true
       dividerField.set(this,getResources().getDrawable(R.drawable.dot_orange))
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

И применить его

  setDividerColor(yourNumberPicker); // for java method
  yourNumberPicker.setDividerColor(Color.RED) // for kotlin method

Ответ 5

Я новичок в Android, поэтому имейте в виду, что это решение может быть не очень хорошей практикой, но я нашел (хакерский) способ получить этот эффект, используя только отражение XML/WITHOUT.

Я смог "изменить" цвета разделителей на моем NumberPickers в LinearLayout, добавив 2 тонких горизонтальных представления в ViewGroup и предоставив им отрицательные макеты и желаемый цвет для их фона:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_gravity="center_horizontal"
    android:gravity="center"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    >
    <NumberPicker
        android:layout_width="70dip"
        android:layout_height="wrap_content"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:layout_gravity="center"
        android:layout_margin="5dp"
        />

    <View
        android:layout_height="2dp"
        android:layout_width="70dp"
        android:background="@color/myColor"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="-75dp"
        android:layout_marginBottom="-25dp">

    </View>

    <View
        android:layout_height="2dp"
        android:layout_width="70dp"
        android:background="@color/myColor"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="-70dp"
        android:layout_marginBottom="25dp">

    </View>

</LinearLayout>

По общему признанию, я фактически не меняю цвет, но добавляю новые строки с моим желаемым цветом поверх встроенных разделителей. Надеюсь, это кому-то поможет!

Возможно, вам придется играть с полями, но эти настройки были идеальны для моего настраиваемого диалога.

Ответ 6

Вы можете использовать отражение, чтобы сделать трюк. Вот мое решение

public class ColorChangableNumberPicker extends NumberPicker {

    public ColorChangableNumberPicker(Context context) {
        super(context);
        init();
    }

    public ColorChangableNumberPicker(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ColorChangableNumberPicker(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public ColorChangableNumberPicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init() {
        setDividerColor(Color.RED);
    }


    public void setDividerColor(@ColorInt int color) {
        try {
            Field fDividerDrawable = NumberPicker.class.getDeclaredField("mSelectionDivider");
            fDividerDrawable.setAccessible(true);
            Drawable d = (Drawable) fDividerDrawable.get(this);
            d.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
            d.invalidateSelf();
            postInvalidate(); // Drawable is dirty
        }
        catch (Exception e) {

        }
    }
}

Ответ 7

Я использую приведенный ниже код, чтобы изменить разделитель, а не непосредственно цвет, но вы можете сделать это с помощью png как это.

Это решение, которое я вам приношу, происходит от здесь, но мой код - это простое упрощение для изменения разделителя и его.

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

Ответ 8

используя этот код для evry, и вы хотите сделать с делителем

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

Ответ 9

Лучше хранить частное поле, если вы собираетесь менять цвет разделителя в будущем. Вот так:

@Nullable private Field dividerField;

public void setDivider(@Nullable Drawable divider) {
    try {
        if (dividerField == null) {
            dividerField = NumberPicker.class.getDeclaredField("mSelectionDivider");
            dividerField.setAccessible(true);
        }

        dividerField.set(this, divider);
    } catch (Exception ignore) {}
}

Ответ 10

Это легко с моей библиотекой (я тоже свернул свой NumberPicker).

<com.github.tomeees.scrollpicker.ScrollPicker
    ...
    app:selectorColor="..."
    />

Ответ 11

Простейший способ - добавить этот атрибут в селектор NumberPicker в xml

android:selectionDivider="@colors/your_color"