Android NumberPicker使用

avatar
作者
猴君
阅读量:0

Android NumberPicker使用

NumberPicker是一个滑动的控件,和spinner差不多。

数字选择器NumberPicker是Android3.0之后出的一个控件,所以如果要兼容3.0之前的版本就需要用到GitHub上的开源项目,下载地址是https://github.com/SimonVT/android-numberpicker

使用

1.首先在xml文件中引入NumberPicker控件

<NumberPicker     android:id="@+id/np"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     app:layout_constraintLeft_toLeftOf="parent"     app:layout_constraintRight_toRightOf="parent"    app:layout_constraintTop_toBottomOf="@+id/number_picker_use" /> 

2.在activity中找到NumberPicker,设置方法

NumberPicker numberPicker = findViewById(R.id.np); String[] datas = new String[]{"北京", "上海", "广州", "深圳"}; numberPicker.setDisplayedValues(datas); //设置文字 numberPicker.setMaxValue(datas.length - 1); //设置最大值,最大值是datas[3] numberPicker.setMinValue(0); numberPicker.setDescendantFocusability(DatePicker.FOCUS_BEFORE_DESCENDANTS); numberPicker.setValue(1); 

常用方法

设置最大值
mNumberPicker.setMaxValue(10); //设置最大值,只能传入int 
设置最小值
 mNumberPicker.setMinValue(0); //设置最小值 
设置当前值
mNumberPicker.setValue(5); //设置当前值 
获取当前值
int value = mNumberPicker.getValue(); //获取当前值 getMaxValue()获取最大值 getMinValue()获取最小值 

有一点需要注意的数值不能用负数。

获取设置的数据
String[] data = numberPicker.getDisplayedValues();//返回一组数据 
获取/设置文本颜色、文本大小、固定颜色
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {             numberPicker.setTextColor(Color.RED);//设置所有的文本都是红色             numberPicker.setTextSize(20);//文字大小,这里最好使用px转dp             numberPicker.setSelectionDividerHeight(40);//两道分割线的高度         }          getTextColor         getTextSize getSelectionDividerHeight 
设置监听

NumberPicker有三个监听分别是OnValueChangeListener、OnScrollListener、Formatter

OnValueChangeListener值改变监听
mNumberPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {             /**              * 每当选择的值改变时都会调用一次              * @param oldVal 改变前的值              * @param newVal 改变后的值              */             @Override             public void onValueChange(NumberPicker picker, int oldVal, int newVal) {                 //做想做的事             }         }); 

每当选择的值改变都会调用一次这个方法,选择的值改变也就是显示在中间的那个值改变。

OnScrollListener滑动事件

实例代码如下

mNumberPicker.setOnScrollListener(new NumberPicker.OnScrollListener() {             @Override             public void onScrollStateChange(NumberPicker view, int scrollState) {                 switch (scrollState){                     case SCROLL_STATE_FLING:                         //手离开之后还在滑动                         break;                     case SCROLL_STATE_IDLE:                         //停止滑动                         break;                     case SCROLL_STATE_TOUCH_SCROLL:                         //正在滑动                         break;                 }             }         }); 

滑动事件就是监听控件滑动时的状态
滑动事件有三个状态

  1. SCROLL_STATE_FLING ——>手离开之后还在滑动
  2. SCROLL_STATE_IDLE ——>停止滑动
  3. SCROLL_STATE_TOUCH_SCROLL ——>正在滑动
Formatter监听设置格式化程序用于格式化当前值

实例代码如下

mNumberPicker.setFormatter(new NumberPicker.Formatter() {             @Override             public String format(int value) {                 //做一些格式转换                 return "返回转换后要显示的内容";             }         }); 

这个监听是用于做一些格式转换的,比如把10以下的数前面加个0显示(01、02、03……),也能理解为转换器,下面我会为大家介绍如何利用Formatter监听设置10以下的数前面加0显示。
我们需要注意一下不能返回空

mNumberPicker.setMaxValue(20); mNumberPicker.setMinValue(0); mNumberPicker.setValue(0); mNumberPicker.setFormatter(new NumberPicker.Formatter() {         @Override         public String format(int value) {             String data;             if (value < 10) {                 data = "0" + value;//让小于10的数前面加个0再输出             } else {                 data = String.valueOf(value); //大于10的数就不变             }             return data;         }     }); 
循环滚动

要设置是否循环滚动只需要使用一个方法就可以了

mNumberPicker.setWrapSelectorWheel(true); //设置循环滚动 

设置false代表不循环滚动,true代表循环滚动
该方法需要注意的是

  • 一定要设置好最大值才有效果
  • 最大值必须大于等于3
禁止编辑

java代码

mNumberPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); //禁止输入 

xml设置

android:descendantFocusability="blocksDescendants" 
28的版本以前修改分界线
/**  * 设置picker分割线的颜色  */ private void setDividerColor(NumberPicker picker) {     Field field = null;     try {         field = NumberPicker.class.getDeclaredField("mSelectionDivider");         if (field != null) {             field.setAccessible(true);             field.set(picker, new ColorDrawable(Color.RED));         }     } catch (NoSuchFieldException e) {         e.printStackTrace();     } catch (IllegalAccessException e) {         e.printStackTrace();     }  }  /**  * 设置picker分割线的宽度(分割线的粗细)  */ private void setNumberPickerDivider(NumberPicker picker) {     Field[] fields = NumberPicker.class.getDeclaredFields();     for (Field f : fields) {         if (f.getName().equals("mSelectionDividerHeight")) {             f.setAccessible(true);             try {                 f.set(picker, 1);             } catch (IllegalAccessException e) {                 e.printStackTrace();             }             break;         }     } } 
案例:日期选择器
xml布局
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     android:layout_width="match_parent"     android:layout_height="wrap_content">      <TextView         android:gravity="center"         android:padding="10dp"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:text="请选择时间"         android:textSize="18sp"         android:textStyle="bold"         app:layout_constraintLeft_toLeftOf="parent"         app:layout_constraintTop_toTopOf="parent"         app:layout_constraintBottom_toBottomOf="@+id/button_confirm"/>      <Button         android:layout_margin="10dp"         android:id="@+id/button_confirm"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:text="确认"         app:layout_constraintRight_toRightOf="parent"         app:layout_constraintTop_toTopOf="parent" />      <LinearLayout         android:id="@+id/item_linear_layout"         android:layout_width="match_parent"         android:layout_height="wrap_content"         android:layout_marginStart="16dp"         android:layout_marginEnd="16dp"         android:gravity="fill_horizontal"         app:layout_constraintTop_toBottomOf="@+id/button_confirm"         app:layout_constraintBottom_toBottomOf="parent"         app:layout_constraintLeft_toLeftOf="parent"         app:layout_constraintRight_toRightOf="parent">          <NumberPicker             android:id="@+id/number_picker_year"             android:layout_width="0dp"             android:layout_height="200dp"             android:layout_weight="0.2"             android:descendantFocusability="blocksDescendants" />          <TextView             android:id="@+id/text_view_year"             android:layout_width="0dp"             android:layout_height="200dp"             android:layout_weight="0.05"             android:gravity="center"             android:text="@string/text_year" />          <NumberPicker             android:id="@+id/number_picker_month"             android:layout_width="0dp"             android:layout_height="200dp"             android:layout_weight="0.15"             android:descendantFocusability="blocksDescendants" />          <TextView             android:id="@+id/text_view_month"             android:layout_width="0dp"             android:layout_height="200dp"             android:layout_weight="0.05"             android:gravity="center"             android:text="@string/text_month" />          <NumberPicker             android:id="@+id/number_picker_date"             android:layout_width="0dp"             android:layout_height="200dp"             android:layout_weight="0.15"             android:descendantFocusability="blocksDescendants" />          <TextView             android:id="@+id/text_view_date"             android:layout_width="0dp"             android:layout_height="200dp"             android:layout_weight="0.05"             android:gravity="center"             android:text="@string/text_date" />          <NumberPicker             android:id="@+id/number_picker_hour"             android:layout_width="0dp"             android:layout_height="200dp"             android:layout_weight="0.15"             android:descendantFocusability="blocksDescendants" />          <TextView             android:id="@+id/text_view_hour"             android:layout_width="0dp"             android:layout_height="200dp"             android:layout_weight="0.05"             android:gravity="center"             android:text="@string/text_time_symbol" />          <NumberPicker             android:id="@+id/number_picker_minute"             android:layout_width="0dp"             android:layout_height="200dp"             android:layout_weight="0.15"             android:descendantFocusability="blocksDescendants" />      </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout> 
dialogfragment
import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.NumberPicker;  import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.DialogFragment;  import com.zg.pdfdemo.R;  import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Locale;  /***  * @Description:  * //[Android构建自定义日期时间选择器](https://www.jianshu.com/p/05dade729e28)  */ public class TimePickerDialog extends DialogFragment implements NumberPicker.OnValueChangeListener {      private NumberPicker yearPicker;     private NumberPicker monthPicker;     private NumberPicker datePicker;     private NumberPicker hourPicker;     private NumberPicker minutePicker;      @Nullable     @Override     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {         View view = inflater.inflate(R.layout.dialog_fragment_date_time_picker, container, false);         return view;     }      @Override     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {         super.onViewCreated(view, savedInstanceState);         Calendar calendar = Calendar.getInstance();         yearPicker = view.findViewById(R.id.number_picker_year);         monthPicker = view.findViewById(R.id.number_picker_month);         datePicker = view.findViewById(R.id.number_picker_date);         hourPicker = view.findViewById(R.id.number_picker_hour);         minutePicker = view.findViewById(R.id.number_picker_minute);          //限制年份范围为前后五年         int yearNow = calendar.get(Calendar.YEAR);         yearPicker.setMinValue(yearNow - 5);         yearPicker.setMaxValue(yearNow + 5);         yearPicker.setValue(yearNow);         yearPicker.setWrapSelectorWheel(true);  //关闭选择器循环          //设置月份范围为1~12         monthPicker.setMinValue(1);         monthPicker.setMaxValue(12);         monthPicker.setValue(calendar.get(Calendar.MONTH) + 1);         monthPicker.setWrapSelectorWheel(true);          //日期限制存在变化,需要根据当月最大天数来调整         datePicker.setMinValue(1);         datePicker.setMaxValue(calendar.getActualMaximum(Calendar.DAY_OF_MONTH));         datePicker.setValue(calendar.get(Calendar.DATE));         datePicker.setWrapSelectorWheel(true);          //24小时制,限制小时数为0~23         hourPicker.setMinValue(0);         hourPicker.setMaxValue(23);         hourPicker.setValue(calendar.get(Calendar.HOUR_OF_DAY));         hourPicker.setWrapSelectorWheel(true);          //限制分钟数为0~59         minutePicker.setMinValue(0);         minutePicker.setMaxValue(59);         minutePicker.setValue(calendar.get(Calendar.MINUTE));         minutePicker.setWrapSelectorWheel(true);          //为年份和月份设置监听         yearPicker.setOnValueChangedListener(this);         monthPicker.setOnValueChangedListener(this);          view.findViewById(R.id.button_confirm).setOnClickListener(v -> {             //获取的日期时间结果             String result = String.format(Locale.CHINA, "%d-%d-%d %d:%d",                     yearPicker.getValue(), monthPicker.getValue(), datePicker.getValue(),                     hourPicker.getValue(), minutePicker.getValue());             Log.i("zxd", "日期时间: " + result);             dismiss();         });     }      @Override     public void onValueChange(NumberPicker picker, int oldVal, int newVal) {         String dateStr = String.format(Locale.CHINA, "%d-%d", yearPicker.getValue(), monthPicker.getValue());         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM", Locale.CHINA);         Calendar calendar = Calendar.getInstance();         try {             calendar.setTime(simpleDateFormat.parse(dateStr));         } catch (ParseException e) {             e.printStackTrace();         }         int dateValue = datePicker.getValue();         int maxValue = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);         datePicker.setMaxValue(maxValue);         //重设日期值,防止月份变动时超过最大值         datePicker.setValue(Math.min(dateValue, maxValue));     } } 

当选择器日期发生变化时,我们需要判断所显示的日期月份最多有多少天,防止出现不存在日期的情况,这时就需要为选择器值变动监听,因为年份和月份的变动都会影响当月最大天数,因此可以通过实现NumberPicker.OnValueChangeListener,重写onValueChange()方法来实现:

@Override     public void onValueChange(NumberPicker picker, int oldVal, int newVal) {         String dateStr = String.format(Locale.CHINA, "%d-%d", yearPicker.getValue(), monthPicker.getValue());         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM", Locale.CHINA);         Calendar calendar = Calendar.getInstance();         try {             calendar.setTime(simpleDateFormat.parse(dateStr));         } catch (ParseException e) {             e.printStackTrace();         }         int dateValue = datePicker.getValue();         int maxValue = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);         datePicker.setMaxValue(maxValue);         //重设日期值,防止月份变动时超过最大值         datePicker.setValue(Math.min(dateValue, maxValue));     } 

这样一个自定义的可以同时选择日期和时间的选择器就基本完工了,以后还能自定义各个控件的样式来实现想要的效果。当然,获取选择器的结果可以通过定义一个Button来监听点击事件来获取

findViewById(R.id.button_confirm).setOnClickListener(view -> {     //获取的日期时间结果     String result = String.format(Locale.CHINA, "%d-%d-%d %d:%d",             yearPicker.getValue(), monthPicker.getValue(), datePicker.getValue(),             hourPicker.getValue(), minutePicker.getValue()); } 

参考链接

Android构建自定义日期时间选择器

数字选择器NumberPicker使用教程

安卓NumberPicker数字选择器用法

第三方的NumberPicker

Android进阶之路——自定义NumberPicker

NumberPicker源码分析+自定义View简单实现NumberPicker

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!