webentwicklung-frage-antwort-db.com.de

Ändern der NumberPicker-Teilerfarbe

In den letzten Android-Versionen verwenden Number Pickers beim Zeichnen einen blauen Trenner (siehe Abbildung unten).

enter image description here

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)
30
Laurent

Basierend auf diesem ( https://stackoverflow.com/a/20291416/2915480 obwohl es sich um DatePicker handelt) gibt es mehrere Möglichkeiten:

  1. Schreiben Sie Ihren eigenen NumberPicker ohne mSelectionDivider und seine verbundenen Unternehmen oder verwenden Sie die Rückportierung von Vikram . Im letzten Fall: 

    1. download aus lib von github
    2. zeichnen in res/drawable-xxx/np_numberpicker_selection_divider.9.png ändern:

      • zu transparent (oder was auch immer) .9.png 
      • erstellen Sie die Formlinienressource np_numberpicker_selection_divider.xml in res/drawable (mit 0dp-Höhe oder transparenter Farbe).
    3. ODER entfernen Sie if (mSelectionDivider != null) aus der onDraw (Canvas) -Methode in NumberPicker.Java like hier

  2. Ü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. 

18

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);
59
gabin

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>
30
Rubin Yoo

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
10
stannums

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. 

3
JDune

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) {

        }
    }
}
2
Bojan Kseneman

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;
        }
    }
1
SerSánGal

Mit meiner Bibliothek ist es einfach (ich habe auch meinen eigenen NumberPicker gerollt). 

<com.github.tomeees.scrollpicker.ScrollPicker
    ...
    app:selectorColor="..."
    />
0
Tamás Sajti

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) {}
}
0
0neel

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