使用Android组件NumberPicker定制日期选择器

来源:互联网 发布:淘宝靠谱的男装外贸店 编辑:程序博客网 时间:2024/05/21 05:40

使用Android组件NumberPicker定制日期选择器

黄途文 发布于 2015年06月17日 11时, 0评/1584阅
分享到: 
收藏+2
踩顶0
日期选择器,在很多项目中都有定制需求,在我们项目中使用的是NumberPicker来定制自己的选择器,使用过程中发现很多不足的地方,
业务需求,日期(day)的变化,小时(hour)会有所变化,小时不一定是0-23,可能是15-23,
标签: <无>

代码片段(4)[全屏查看所有代码]

1. [代码]先贴两段神奇的代码     

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//mHour为NumberPicker对象
//注意 以下两行代码顺序不能变,变后会出现数组下表越界的错误setMaxValue在前
mHour.setMaxValue(todayHourStrs.length-1);
setWrapSelectorWheel();
mHour.setDisplayedValues(todayHourStrs);
 
 
//需要先扩大DisplayedValues再setMaxValue,否则会跑出数组下标越界
mHour.setDisplayedValues(hourStrsEmpty);
mHour.setMaxValue(hourStrs.length-1);
setWrapSelectorWheel();
mHour.setDisplayedValues(hourStrs);
 
 
privatevoid setWrapSelectorWheel(){
  /* setWrapSelectorWheel
  * 必须放在setMaxValue后面,因为源码在更改此值的时候要求MaxValue-MinValue>=mSelectorIndices.length(等于3)
  * 所以如果MaxValue-MinValue更改了需要重新调用setWrapSelectorWheel
  */
  mDay.setWrapSelectorWheel(false);
  mHour.setWrapSelectorWheel(false);
  mMinute.setWrapSelectorWheel(false);
}

2. [代码]再来看Android的源码     

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
  * Sets whether the selector wheel shown during flinging/scrolling should
  * wrap around the {@link NumberPicker#getMinValue()} and
  * {@link NumberPicker#getMaxValue()} values.
  * <p>
  * By default if the range (max - min) is more than the number of items shown
  * on the selector wheel the selector wheel wrapping is enabled.
  * </p>
  * <p>
  * <strong>Note:</strong> If the number of items, i.e. the range (
  * {@link #getMaxValue()} - {@link #getMinValue()}) is less than
  * the number of items shown on the selector wheel, the selector wheel will
  * not wrap. Hence, in such a case calling this method is a NOP.
  * </p>
  *
  * @param wrapSelectorWheel Whether to wrap.
  */
 publicvoid setWrapSelectorWheel(booleanwrapSelectorWheel) {
     finalboolean wrappingAllowed = (mMaxValue - mMinValue) >= mSelectorIndices.length;
     if((!wrapSelectorWheel || wrappingAllowed) && wrapSelectorWheel != mWrapSelectorWheel) {
         mWrapSelectorWheel = wrapSelectorWheel;
     }
 }
 
 
 /**
  * Sets the min value of the picker.
  *
  * @param minValue The min value inclusive.
  *
  * <strong>Note:</strong> The length of the displayed values array
  * set via {@link #setDisplayedValues(String[])} must be equal to the
  * range of selectable numbers which is equal to
  * {@link #getMaxValue()} - {@link #getMinValue()} + 1.
  */
 publicvoid setMinValue(intminValue) {
     if(mMinValue == minValue) {
         return;
     }
     if(minValue < 0) {
         thrownew IllegalArgumentException("minValue must be >= 0");
     }
     mMinValue = minValue;
     if(mMinValue > mValue) {
         mValue = mMinValue;
     }
     booleanwrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length;
     setWrapSelectorWheel(wrapSelectorWheel);
     initializeSelectorWheelIndices();
     updateInputTextView();
     tryComputeMaxWidth();
     invalidate();
 }
 
 
 
 /**
  * Sets the values to be displayed.
  *
  * @param displayedValues The displayed values.
  *
  * <strong>Note:</strong> The length of the displayed values array
  * must be equal to the range of selectable numbers which is equal to
  * {@link #getMaxValue()} - {@link #getMinValue()} + 1.
  */
 publicvoid setDisplayedValues(String[] displayedValues) {
     if(mDisplayedValues == displayedValues) {
         return;
     }
     mDisplayedValues = displayedValues;
     if(mDisplayedValues != null) {
         // Allow text entry rather than strictly numeric entry.
         mInputText.setRawInputType(InputType.TYPE_CLASS_TEXT
                 | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
     }else{
         mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
     }
     updateInputTextView();
     initializeSelectorWheelIndices();
     tryComputeMaxWidth();
 }

3. [代码]代码分析1     

?
1
2
3
4
5
6
7
8
//根据需求,要实现NumberPicker的items动态数量、内容动态变化。所以需要执行以下代码
mHour.setMaxValue(maxValue);
mHour.setDisplayedValues(displayedValues);
//这里要需要注意的是setMaxValue。如果mHour对象原本的displayedValues数组lengths小于即将设置的maxValue。那么,执行setMaxValue就会跑出数组下表越界( java.lang.ArrayIndexOutOfBoundsException)
//相反,如果代码顺序为:
mHour.setDisplayedValues(displayedValues);
mHour.setMaxValue(maxValue);
//那么,这里需要注意setDisplayedValues。如果mHour对象原本的maxValue大于即将甚至的displayedValues数组的lengths,那么,执行setDisplayedValues就会跑出数组下表越界( java.lang.ArrayIndexOutOfBoundsException)

4. [代码]代码分析2     跳至 [1] [2] [3] [4] [全屏预览]

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//需求:选择日期的时候,不需要循环(WrapSelectorWheel),
//例如:选择小时 02,下拉一格改为 01 ,在下拉一格就不是23了,而是不能下拉
//要实现这样的功能,NumberPicker提供了一个API:setWrapSelectorWheel,设置为false,即可
 
mHour.setDisplayedValues(hourStrsEmpty);
mHour.setMaxValue(maxValue);
setWrapSelectorWheel();
mHour.setDisplayedValues(hourStrs);
 
 
 
mHour.setWrapSelectorWheel(false);
//注意,只有mHour对象的maxValue-minValue>=mSelectorIndices.length时。执行setWrapSelectorWheel才会有效。而mSelectorIndices数组的长度为3。
//再注意,设置了setWrapSelectorWheel后需要执行setDisplayedValues。才会更新列表,此列表才不是循环的。所以才会有以上这样的代码顺序。
//由于maxValue>hourStrs.length,所以,需要先执行setDisplayedValues,再由于执行setDisplayedValues如果传入的数组等于原来的数组,就不会更新,所以需要传入一个hourStrsEmpty。hourStrsEmpty数组内容不能有null,长度等于hourStrs
举报


开源中国-程序员在线工具:Git代码托管 API文档大全(120+) JS在线编辑演示 二维码 更多»

0 0
原创粉丝点击