In den letzten Android-Versionen verwenden Number Pickers beim Zeichnen einen blauen Trenner (siehe Abbildung unten).
Ich möchte diese Farbe ändern. Gibt es eine funktionierende Lösung? oder vielleicht eine Bibliothek, die eine aktualisierte Version von NumberPicker enthält, mit der die Farbe des Teilers angepasst werden kann?
Ich habe versucht, Android-numberpicker , aber ich bekomme zur Laufzeit einen Fehler (siehe unten) aufgrund von Code aus der Bibliothek, der versucht, auf eine Ressourcen-ID zuzugreifen, die nicht vorhanden ist.
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)
Basierend auf diesem ( https://stackoverflow.com/a/20291416/2915480 obwohl es sich um DatePicker handelt) gibt es mehrere Möglichkeiten:
Schreiben Sie Ihren eigenen NumberPicker ohne mSelectionDivider und seine verbundenen Unternehmen oder verwenden Sie die Rückportierung von Vikram . Im letzten Fall:
zeichnen in res/drawable-xxx/np_numberpicker_selection_divider.9.png ändern:
0dp
-Höhe oder transparenter Farbe).ODER entfernen Sie if (mSelectionDivider != null)
aus der onDraw (Canvas) -Methode in NumberPicker.Java like hier
Über Reflektion können Sie auf private final field mSelectionDivider
zugreifen (Details: https://github.com/Android/platform_frameworks_base/blob/master/core/Java/Android/widget/NumberPicker.Java ) - z. siehe Modifikation hier . Ich habe Reflexion benutzt, aber es ist nicht die beste Lösung.
Wenn Sie einfach die Farbe ändern möchten (basierend auf Stannums antworten):
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;
}
}
}
Und danach
setDividerColor(mNumberPicker, Color.GREEN);
Das hat für mich funktioniert, ohne die Reflexion zu benutzen.
my_layout.xml
<NumberPicker
...
Android:theme="@style/DefaultNumberPickerTheme" />
Styles.xml (AppTheme ist mein App-Thema in der App)
<style name="DefaultNumberPickerTheme" parent="AppTheme">
<item name="colorControlNormal">@color/dividerColor</item>
</style>
Ich verwende eine Workaround-Java-Methode:
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;
}
}
//}
}
oder Kotlin-Methode:
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()
}
}
Und bewerben Sie sich
setDividerColor(yourNumberPicker); // for Java method
yourNumberPicker.setDividerColor(Color.RED) // for kotlin method
Ich bin relativ neu für Android. Denken Sie daran, dass diese Lösung keine gute Praxis ist, aber ich habe einen (hackigen) Weg gefunden, um diesen Effekt zu erzielen, indem Sie nur XML/WITHOUT-Reflektion verwenden.
Ich konnte die Farben der Teiler meiner NumberPicker innerhalb eines LinearLayout 'ändern', indem ich der ViewGroup zwei dünne horizontale Ansichten hinzufügte und ihnen negative Layoutränder und meine gewünschte Farbe für ihre Hintergründe gab:
<?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>
Zugegeben, ich ändere eigentlich nicht die Farbe, sondern füge neue Linien mit meiner gewünschten Farbe über den eingebauten Trennwänden hinzu. Hoffentlich hilft das sowieso jemandem!
Sie müssen möglicherweise mit den Rändern spielen, aber diese Einstellungen waren perfekt für meinen benutzerdefinierten Dialog.
Sie können Reflektion verwenden, um den Trick auszuführen. Hier ist meine Lösung
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) {
}
}
}
Ich benutze den untenstehenden Code, um den Teiler zu ändern, nicht direkt die Farbe, aber Sie können das mit einem png wie diesem tun.
Diese Lösung, die ich Ihnen mitbringe, stammt von here , aber mein Code ist eine einfache Vereinfachung, um den Teiler zu ändern, und das ist es.
// 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;
}
}
Mit meiner Bibliothek ist es einfach (ich habe auch meinen eigenen NumberPicker gerollt).
<com.github.tomeees.scrollpicker.ScrollPicker
...
app:selectorColor="..."
/>
Es ist besser, ein privates Feld zu speichern, wenn Sie in Zukunft die Farbe des Teilers ändern möchten. So was:
@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) {}
}
verwenden Sie diesen Code für alle Dinge, die Sie mit Divider tun möchten
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;
}
}