Android 更改数字切分器颜色

Android 更改数字切分器颜色,android,android-styles,numberpicker,Android,Android Styles,Numberpicker,在最近的android版本中,绘制时使用蓝色分隔符(参见下图) 我想换一下这个颜色。有有效的解决办法吗?或者可能是一个库,它打包了NumberPicker的更新版本,允许自定义分隔器颜色 我已经尝试过了,但在运行时由于库中的某些代码试图访问不存在的资源id而出现错误(请参见下文) android.content.res.Resources$NotFoundException: Resource ID #0x0 at android.content.res.Resources.g

在最近的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)
android.content.res.Resources$NotFoundException:资源ID#0x0
位于android.content.res.Resources.getValue(Resources.java:1123)
位于android.content.res.Resources.loadXmlResourceParser(Resources.java:2309)
位于android.content.res.Resources.getLayout(Resources.java:939)
在android.view.LayoutInflater.inflate(LayoutInflater.java:395)
在net.simonvt.numberpicker.numberpicker.(numberpicker.java:635)
net.simonvt.numberpicker.numberpicker.(numberpicker.java:560)
在net.simonvt.numberpicker.numberpicker.(numberpicker.java:550)
基于此(尽管是关于日期选择器),有几种方法:

  • 编写自己的NumberPicker,无需mSelectionDivider及其附属公司,或使用backported by。在最后一种情况下:
  • 从lib下载
  • 更改res/drawable xxx/np\u numberpicker\u selection\u divider.9.png中的可绘制内容:
    • 到透明的(或任何东西)。9.png *以res/drawable格式创建np_numberpicker_selection_divider.xml形状线资源(使用
      0dp
      高度或透明颜色)
  • 或者从类似的onDraw(Canvas)方法中删除
    if(mSelectionDivider!=null)
    分支

  • 使用反射访问
    专用最终字段mSelectionDivider
    (详细信息:)-例如,请参见修改。 我使用了反射,但这不是最好的解决方案

  • 使用主题化覆盖API 21+中数字选择器的分隔符颜色:
    ?attr/colorControlNormal
    确定材质数字选择器中分隔符的颜色,因此在小部件的主题中更改此颜色将实现此功能,例如,对于日期选择器:

  • 
    ?颜色重音
    
    在小部件中:

     <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" />
    

    我使用下面的代码来更改分隔符,而不是直接更改颜色,但您可以使用png来更改分隔符

    我给你们带来的这个解决方案来自于,但我的代码是一个简单的方法来改变除法器,就是这样

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

    我正在使用变通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
    

    如果您只想更改颜色(基于标准答案):

    然后呢

    setDividerColor(mNumberPicker, Color.GREEN);
    

    将此代码用于你想用除法器做的任何事情

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

    您可以使用反射来完成此操作。这是我的解决办法

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

    最简单的方法是在xml中的NumberPicker选择器中添加此属性

    android:selectionDivider="@colors/your_color"
    

    我对安卓相当陌生,所以请记住,这个解决方案可能不是一个好的实践,但我找到了一种(黑客)方法,只使用XML/而不使用反射来获得这种效果

    通过向视图组中添加两个薄的水平视图,并为它们提供负的布局边距和我所需的背景颜色,我可以在线性布局中“更改”我的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>
    
    
    
    诚然,我实际上并没有改变颜色,而是在内置的分隔器上添加了带有我想要的颜色的新线条。希望这对其他人有帮助


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

    这在不使用反射的情况下对我有效

    my_layout.xml

    <NumberPicker
       ...
       android:theme="@style/DefaultNumberPickerTheme" />
    
    
    
    Styles.xml(AppTheme是应用程序中的我的应用程序主题)

    
    @颜色/分割颜色
    
    如果将来要更改分隔符颜色,最好存储一个私有字段。像这样:

    @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) {}
    }
    
    我的电脑很简单(我也玩了自己的数字游戏)


    实际上,您可以通过编写自定义主题来更改分隔符的颜色

    例如,将此添加到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>
    
    
    @android:彩色/白色
    @安卓:彩色/全息绿/深色
    @android:彩色/黑色
    @android:彩色/白色
    30便士
    
    并将此主题添加到您的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>
    
    @android:color/transparent
    
    这是否回答了您的问题?:不,它不起作用。第一个旨在创建自定义样式的答案无效,因为无法解析符号“@style/Holo.NumberPicker”。对于第二个答案,结果是相同的:在反射检索的字段mSelectionDivider上调用set(numberPicker,color)无效。感谢您的帮助。解决方案2工作得很好,但我没能让解决方案1工作。最后,NumberPicker.java中与变量DEFAULT_LAYOUT_resource_id关联的资源id似乎不再有效。最后但同样重要的是,我的目标是将颜色更改为自定义颜色,而不是隐藏分隔符。为了实现这一目标,我没有将
    mSelectionDivider
    设置为
    null
    ,而是将其等同于一个drawable,它是一个简单的九块PNG,加载了
    getResources().getDrawable(R.drawable.np\u numberpicker\u selection\u divider)
    很好的更改。我注意到的一件事是确保使用“newColorDrawable(ctx.getResources().getColor(R.color.whatevercolor))”而不是“newColorDrawable(R.color.whatevercolor)”,我真的认为这应该标记为一个尝试性的答案!这真的很简单和工作!可能更好:
    colordawable colordawable=new colordawable(ContextCompat.getColor(getContext(),R.color.primaryColor))<com.github.tomeees.scrollpicker.ScrollPicker
        ...
        app:selectorColor="..."
        />
    
    <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
            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>