更改 NumberPicker 分隔线颜色
Posted
技术标签:
【中文标题】更改 NumberPicker 分隔线颜色【英文标题】:Changing NumberPicker divider color 【发布时间】:2014-08-05 16:19:03 【问题描述】:在最近的 android 版本中,number pickers 在绘制时使用蓝色分隔线(参见下图)。
我想改变这个颜色。有可行的解决方案吗?或者可能是一个包含允许自定义分隔线颜色的 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)
【问题讨论】:
这能回答你的问题吗?:***.com/questions/18804762/… 不,它不起作用。旨在创建自定义样式的第一个答案不起作用,因为无法解析符号“@style/Holo.NumberPicker”。对于第二个答案,结果是一样的:在反射检索到的字段 mSelectionDivider 上调用 set(numberPicker, color) 没有效果。 【参考方案1】:科特林
您可以通过这种方式更改分隔符编号,而无需版本控制。本例设置透明颜色:
private fun setDividerColor(picker: NumberPicker)
val dividerField = NumberPicker::class.java.declaredFields.firstOrNull it.name == "mSelectionDivider" ?: return
try
val colorDrawable = ColorDrawable(android.graphics.Color.TRANSPARENT)
dividerField.isAccessible = true
dividerField.set(picker, colorDrawable)
catch (e: Exception)
e.printStackTrace()
【讨论】:
【参考方案2】:其实你可以写一个自定义主题来改变分隔线的颜色。
作为示例将其添加到您的主题.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_
android:layout_
android:theme="@style/NumberPickerTheme"
/>
如果你想摆脱分隔线,只需使用
<item name="colorControlNormal">@android:color/transparent</item>
【讨论】:
【参考方案3】:基于此(https://***.com/a/20291416/2915480 虽然是关于 DatePicker)有几种方法:
-
在没有 mSelectionDivider 及其附属机构的情况下编写您自己的 NumberPicker,或使用 Vikram 的反向移植。最后一种情况:
从github的lib下载
更改 res/drawable-xxx/np_numberpicker_selection_divider.9.png 中的可绘制对象:
0dp
高度或透明颜色)。
或从NumberPicker.java 中的onDraw(Canvas) 方法中删除if (mSelectionDivider != null)
分支,例如here
使用反射访问private final field mSelectionDivider
(详细信息:https://github.com/android/platform_frameworks_base/blob/master/core/java/android/widget/NumberPicker.java) - 例如见修改here。
我使用了反射,但这不是最好的解决方案。
在 API 21+ 中使用主题来覆盖数字选择器的分隔线颜色:?attr/colorControlNormal
确定材料编号选择器中分隔线的颜色,因此在小部件的主题中更改此颜色即可,例如对于日期选择器:
<style name="MyAppTheme.NumberPicker" parent=" MyAppTheme">
<item name="android:colorControlNormal"> ?colorAccent </item>
</style>
在小部件中:
<DatePicker
android:id="@+id/question_date"
android:layout_
android:layout_
android:calendarViewShown="false"
android:datePickerMode="spinner"
android:gravity="center"
android:theme="@style/MyAppTheme.NumberPicker" />
【讨论】:
感谢您的帮助。解决方案 2 完美运行,但我未能使解决方案 1 工作。最后,与 NumberPicker.java 中的变量 DEFAULT_LAYOUT_RESOURCE_ID 关联的资源 ID 似乎不再有效。最后但同样重要的是,我的目标是将颜色更改为自定义颜色,而不是隐藏分隔线。为了实现这个目标,我没有将mSelectionDivider
设置为null
,但等于一个drawable,它是一个简单的九个补丁PNG,加载了getResources().getDrawable(R.drawable.np_numberpicker_selection_divider)
【参考方案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;
//
或 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
【讨论】:
【参考方案5】:使用我的library 很容易(我也推出了自己的 NumberPicker)。
<com.github.tomeees.scrollpicker.ScrollPicker
...
app:selectorColor="..."
/>
【讨论】:
com.github.tomeees.scrollpicker.ScrollPicker
及其 app:selectorColor
运行良好,感谢您制作 Tamás Sajti【参考方案6】:
如果您将来要更改分隔线颜色,最好存储一个私有字段。像这样:
@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)
【讨论】:
【参考方案7】:这在不使用反射的情况下对我有用。
my_layout.xml
<NumberPicker
...
android:theme="@style/DefaultNumberPickerTheme" />
Styles.xml(AppTheme是我在应用中的应用主题)
<style name="DefaultNumberPickerTheme" parent="AppTheme">
<item name="colorControlNormal">@color/dividerColor</item>
</style>
【讨论】:
只是一个友好的提醒。 'colorControlNormal',仅适用于 API 21 及更高版本。 如果存在“colorControlNormal”,请提出替代方案 只是想指出使用colorControlNormal
对我不起作用,我必须明确添加android:
前缀,就像<item name="android:colorControlNormal">#ffffff</item>
【参考方案8】:
我对 Android 还很陌生,所以请记住,这种解决方案可能不是一个好的做法,但我找到了一种(hacky)方法来获得这种效果,只使用 XML/不使用反射。
通过向 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_
android:layout_
>
<NumberPicker
android:layout_
android:layout_
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_gravity="center"
android:layout_margin="5dp"
/>
<View
android:layout_
android:layout_
android:background="@color/myColor"
android:layout_gravity="center_vertical"
android:layout_marginLeft="-75dp"
android:layout_marginBottom="-25dp">
</View>
<View
android:layout_
android:layout_
android:background="@color/myColor"
android:layout_gravity="center_vertical"
android:layout_marginLeft="-70dp"
android:layout_marginBottom="25dp">
</View>
</LinearLayout>
诚然,我实际上并没有改变颜色,而是在内置分隔线的顶部添加了我想要的颜色的新线条。希望这对某人有所帮助!
您可能不得不使用边距,但这些设置非常适合我的自定义对话框。
【讨论】:
【参考方案9】:最简单的方法是在 xml 中的 NumberPicker 选择器中添加此属性
android:selectionDivider="@colors/your_color"
【讨论】:
【参考方案10】:您可以使用反射来解决问题。这是我的解决方案
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)
【讨论】:
我认为这是最好的答案。另外,我认为这对于仅自定义一条线来说太过分了……但那是系统故障。你帮了我很多。谢谢【参考方案11】:将此代码用于您想用分隔符做的所有事情
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;
【讨论】:
【参考方案12】:如果您只想更改颜色(基于 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);
【讨论】:
不错的变化。我注意到的一件事是确保使用 'newColorDrawable(ctx.getResources().getColor(R.color.whatevercolor))' 而不是 'new ColorDrawable(R.color.whatevercolor)' 我真的认为,它应该标记为尝试答案!它真的很简单而且很有效! 可能会更好:ColorDrawable colorDrawable = new ColorDrawable(ContextCompat.getColor(getContext(), R.color.primaryColor));
谢谢伙计!我把它翻译成一个 Kotlin 扩展,它工作得很好。【参考方案13】:
我使用下面的代码来改变分隔线,而不是直接改变颜色,但你可以用 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;
【讨论】:
以上是关于更改 NumberPicker 分隔线颜色的主要内容,如果未能解决你的问题,请参考以下文章