更改NumberPicker分隔线颜色

时间:2014-06-15 19:56:27

标签: android android-styles numberpicker

在最近的Android版本中,number pickers在绘制时使用蓝色分隔符(参见下图)。

enter image description here

我想改变这种颜色。有工作的解决方案吗?或者是一个包含更新版本的NumberPicker的库,它允许自定义分隔符颜色?

我尝试了android-numberpicker但是由于库中的一些代码试图访问不存在的资源ID,我在运行时遇到错误(见下文)。

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)

12 个答案:

答案 0 :(得分:59)

如果您只想更改颜色(基于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);

答案 1 :(得分:39)

这对我有用而不使用反射。

my_layout.xml

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

Styles.xml(AppTheme是应用程序中的应用主题)

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

答案 2 :(得分:18)

基于此(https://stackoverflow.com/a/20291416/2915480虽然它关于DatePicker)有几种方法:

  1. 在没有mSelectionDivider及其附属机构的情况下编写您自己的NumberPicker,或使用Vikram后向移植。在最后一种情况:

    1. 从lib github
    2. 下载
    3. 在res / drawable-xxx / np_numberpicker_selection_divider.9.png中更改drawable:

      • 透明(或其他).9.png
      • 在res / drawable中创建np_numberpicker_selection_divider.xml形状线资源(0dp高度或透明色)。
    4. 或删除NumberPicker.java中onDraw(Canvas)方法的if (mSelectionDivider != null)分支,如here

  2. 使用反射来访问private final field mSelectionDivider(详情:https://github.com/android/platform_frameworks_base/blob/master/core/java/android/widget/NumberPicker.java) - 例如见修改here。 我使用反射,但它不是最好的解决方案。

答案 3 :(得分:10)

我使用解决方法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;
            }
        }
        //}
     }

或Kotlin方法:

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

答案 4 :(得分:3)

我对Android很新,所以请记住,这个解决方案可能不是一个好习惯,但我发现(hacky)方法只使用XML / WITHOUT反射来获得此效果。

我能够改变&#39;通过向ViewGroup添加2个薄的水平视图,并为它们的背景提供负的布局边距和我想要的背景颜色,在我的NumberPickers中的分隔线的颜色在LinearLayout中:

<?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>

不可否认,我实际上并没有改变颜色,而是在内置分隔器的顶部添加了所需颜色的新线条。希望无论如何这对某人有帮助!

您可能需要使用边距,但这些设置非常适合我的自定义对话框。

答案 5 :(得分:2)

您可以使用反射来完成这项工作。这是我的解决方案

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

        }
    }
}

答案 6 :(得分:1)

我使用以下代码更改分隔符,而不是直接更改颜色,但您可以使用png like this来执行此操作。

我带给你的这个解决方案来自here,但我的代码是一个简单的简化来更改分隔符,就是这样。

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

答案 7 :(得分:0)

将此代码用于evry,你想要使用divider

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

答案 8 :(得分:0)

如果您将来要更改分隔线颜色,最好存储私有字段。像这样:

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

答案 9 :(得分:0)

使用我的library很容易(我也推出了自己的NumberPicker)。

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

答案 10 :(得分:0)

实际上,您可以在编写自定义主题时更改分隔线的颜色。

例如将其添加到您的 themes.xml

<style name="NumberPickerTheme" parent="Theme.AppCompat.Light">
        <item name="colorAccent">@android:color/white</item>
        
        <!-- Edit this colorControlNormal value as you need -->
        <item name="colorControlNormal">@android:color/holo_green_dark</item>
        
        <item name="android:textColorPrimary">@android:color/black</item>
        <item name="android:background">@android:color/white</item>
        <item name="android:textSize">30sp</item>
    </style>

然后将此主题添加到您的 Numberpicker

<NumberPicker
        android:id="@+id/index_picker1"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:theme="@style/NumberPickerTheme"
         />

如果你想摆脱分隔线,只需使用

<item name="colorControlNormal">@android:color/transparent</item>

答案 11 :(得分:-5)

最简单的方法是在xml

中的NumberPicker选择器中添加此属性
android:selectionDivider="@colors/your_color"