Android 更改 NumberPicker 分隔线颜色
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24233556/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Changing NumberPicker divider color
提问by Laurent
On recent android versions, number pickersuse a blue divider when drawn (cf. image below).
在最近的 android 版本中,数字选择器在绘制时使用蓝色分隔线(参见下图)。
I would like to change this color. Is there a working solution? or perhaps a library that package an updated version of NumberPicker that allows customizing the divider color?
我想改变这个颜色。有没有可行的解决方案?或者也许是一个包含更新版本的 NumberPicker 的库,允许自定义分隔线颜色?
I have tried android-numberpickerbut I get an error (see below) at runtime due to some code from the library that tries to access to a resource id that does not exist.
我尝试过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)
采纳答案by Margarita Litkevych
Based on this (https://stackoverflow.com/a/20291416/2915480although it's about DatePicker) there are several ways:
基于此(https://stackoverflow.com/a/20291416/2915480虽然它是关于 DatePicker )有几种方法:
Write your own NumberPicker without mSelectionDivider and its affiliates or use backported by Vikram. In last case:
- download from lib from github
change drawable in res/drawable-xxx/np_numberpicker_selection_divider.9.png:
- to transparent (or whatever) .9.png
- create np_numberpicker_selection_divider.xml shape line resource in res/drawable (with
0dp
height or transparent color).
OR remove
if (mSelectionDivider != null)
branch from onDraw(Canvas) method in NumberPicker.javalike here
Use reflection to access
private final field mSelectionDivider
(details: https://github.com/android/platform_frameworks_base/blob/master/core/java/android/widget/NumberPicker.java) - e.g. see modification here. I used reflection but it's not the best solution.Use theming to override the number picker's divider color in API 21+:
?attr/colorControlNormal
determines the color of the divider in material number picker, so changing this color in your widget's theme will do the trick, e.g. for DatePicker:
在没有 mSelectionDivider 及其附属公司的情况下编写您自己的 NumberPicker 或使用Vikram 的反向移植。在最后一种情况下:
- 从github 的lib 下载
在 res/drawable-xxx/np_numberpicker_selection_divider.9.png 中更改 drawable:
- 透明(或其他).9.png
- 在 res/drawable 中创建 np_numberpicker_selection_divider.xml 形状线资源(具有
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)-例如,请参阅此处的修改。我使用了反射,但这不是最好的解决方案。在 API 21+ 中使用主题覆盖数字选择器的分隔线颜色:
?attr/colorControlNormal
确定材料数字选择器中分隔线的颜色,因此在小部件的主题中更改此颜色将起作用,例如对于 DatePicker:
<style name="MyAppTheme.NumberPicker" parent=" MyAppTheme">
<item name="colorControlNormal"> ?colorAccent </item>
</style>
and in the widget:
并在小部件中:
<DatePicker
android:id="@+id/question_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:calendarViewShown="false"
android:datePickerMode="spinner"
android:gravity="center"
android:theme="@style/MyAppTheme.NumberPicker" />
回答by gabin
If you want simply to change the color (based on stannums answer):
如果您只想更改颜色(基于 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;
}
}
}
And after that
在那之后
setDividerColor(mNumberPicker, Color.GREEN);
回答by Rubin Yoo
This worked for me without using the reflection.
这对我有用而不使用反射。
my_layout.xml
my_layout.xml
<NumberPicker
...
android:theme="@style/DefaultNumberPickerTheme" />
Styles.xml (AppTheme is my app theme in the app)
Styles.xml(AppTheme 是我在应用中的应用主题)
<style name="DefaultNumberPickerTheme" parent="AppTheme">
<item name="colorControlNormal">@color/dividerColor</item>
</style>
回答by stannums
I'm use workaround Java method:
我正在使用解决方法 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;
}
}
//}
}
or Kotlin method:
或 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()
}
}
And apply its
并应用其
setDividerColor(yourNumberPicker); // for java method
yourNumberPicker.setDividerColor(Color.RED) // for kotlin method
回答by JDune
I'm fairly new to Android so bear in mind that this solution may not be a good practice, but I found a (hacky) way to get this effect using only XML / WITHOUT reflection.
我对 Android 还很陌生,所以请记住,这个解决方案可能不是一个好的做法,但我发现了一种(hacky)方法来仅使用 XML/无反射来获得这种效果。
I was able to 'change' the colors of the dividers on my NumberPickers within a LinearLayout by adding 2 thin, horizontal views to the ViewGroup, and giving them negative layout margins and my desired color for their backgrounds:
通过向 ViewGroup 添加 2 个薄的水平视图,并为它们提供负的布局边距和我想要的背景颜色,我能够“更改”LinearLayout 中 NumberPickers 上分隔线的颜色:
<?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>
Admittedly, I'm not actually changing the color, but adding new lines with my desired color on top of the built-in dividers. Hopefully this helps someone anyway!
诚然,我实际上并没有改变颜色,而是在内置分隔线的顶部添加了带有我想要的颜色的新线条。希望这对某人有所帮助!
You may have to play with the margins, but these settings were perfect for my custom dialog.
您可能不得不使用边距,但这些设置非常适合我的自定义对话框。
回答by Bojan Kseneman
You can use reflection to do the trick. Here is my solution
您可以使用反射来解决问题。这是我的解决方案
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) {
}
}
}
回答by SerSánGal
I use the below code to change the divider, not directly the color, but you can do that with a png like this.
我使用下面的代码来改变分隔符,而不是直接改变颜色,但你可以用这样的 png 来做到这一点。
This solution that I bring you comes from here, but my code is a easy simplification to change the divider and that's it.
我给你带来的这个解决方案来自这里,但我的代码是改变分隔符的简单简化,就是这样。
// 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;
}
}
回答by Tamás Sajti
回答by 0neel
It's better to store a private field if you are going to change divider color in future. Like this:
如果您将来要更改分隔线颜色,最好存储一个私有字段。像这样:
@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) {}
}
回答by Alireza Taghizadeh
using this code for evry thing u want do with 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;
}
}