Android一款UI体验好于NumberPicker的自定义控件NumberPickerView
NumberPickerView
another NumberPicker with more flexible attributes on Android platform
ÏîÄ¿µØÖ·
https://github.com/Carbs0126/NumberPickerView
ÎÄÕµØÖ·£º
http://www.jianshu.com/p/ce33faec2a29
Ç°ÑÔ
ÔÚƽʱ¿ª·¢ÖлáÓõ½NumberPicker×é¼þ£¬µ«ÊÇĬÈÏ·ç¸ñµÄNumberPicker¾ßÓÐһЩ²»Áé»îµÄÊôÐÔ£¬ÇÒ¶¨ÖÆÆðÀ´±È½ÏÂé·³£¬ÇÒȱÉÙһЩ¹ý¶É¶¯Ð§£¬Òò´ËÔÚÓ¦Óÿª·¢Ê±£¬Ò»°ã²ÉÓÃ×Ô¶¨ÒåµÄ¿Ø¼þÀ´Íê³ÉÑ¡Ôñ¹¦ÄÜ¡£
¿Ø¼þ½Øͼ
NumberPickerViewµÄ¶¯Ì¬Í¼£º£¨½Øͼ´¦ÀíÓе㿨£¬Êµ¼ÊЧ¹ûºÜÁ÷³©£©
NumberPickerViewµÄ½Øͼ£º
ʹÓÃNumberPickerView¿ª·¢µÄÒ»¿î¹«Àú/Å©ÀúÑ¡ÔñView£º
¾ßÌåÏîÄ¿µØÖ·¿É¼û£º
https://github.com/Carbs0126/GregorianLunarCalendar
˵Ã÷
NumberPickerViewÊÇÒ»¿îÓëandroidÔÉúNumberPicker¾ßÓÐÀàËƽçÃæÒÔ¼°ÀàËƹ¦ÄܵÄView¡£Ö÷Òª¹¦ÄÜͬÑùÊÇ´Ó¶à¸öºòÑ¡ÏîÖÐͨ¹ýÉÏϹö¶¯µÄ·½Ê½Ñ¡ÔñÐèÒªµÄÑ¡Ïµ«ÊÇÓëNumberPickerÏà±È½Ï£¬Óм¸¸öÖ÷Òª²»Í¬µã£¬ÏÂÃæÊÇÁ½ÕߵIJ»Í¬Ö®´¦¡£
Ôʼ¿Ø¼þÌØÐÔ-NumberPicker
1. ÏÔʾ´°¿ÚÖ»ÄÜÏÔʾ3¸ö±¸Ñ¡Ñ¡Ï
2. ÔÚflingʱ×èÁ¦½Ï´ó£¬ÎÞ·¨¿ìËÙ»¬¶¯£»
3. ÔÚÑ¡ÖÐÓë·ÇÑ¡ÖÐ״̬Çл»±È½ÏÉúÓ²£»
4. ÅúÁ¿¸Ä±äÑ¡ÏîÖеÄÄÚÈÝʱ£¬Ã»Óж¯»Ð§¹û£»
5. ¶¯Ì¬ÉèÖÃwrapģʽʱ(setWrapSelectorWheel()·½·¨)£¬»áÓС°ÔÝʱÏÔʾ²»³ö²¿·ÖÑ¡ÏµÄÎÊÌ⣻
6. Ñ¡ÖÐλÖÃûÓÐÎÄ×Ö˵Ã÷£»
7. ´úÂëÖв»ÄÜ¿ØÖÆÑ¡Ï¶¯¹ö¶¯µ½Ä³Ò»item£»
×Ô¶¨Òå¿Ø¼þÌØÐÔ-NumberPickerView
1. ÏÔʾ´°¿Ú¿ÉÒÔÏÔʾ¶à¸ö±¸Ñ¡Ñ¡Ï
2. flingʱ»¬¶¯ËٶȽϿ죬ÇÒ¿ÉÒÔÉèÖÃĦ²ÁÁ¦£»
3. ÔÚÑ¡ÖÐÓë·ÇÑ¡ÖеÄ״̬»¬¶¯Ê±£¬¾ßÓн¥±äµÄ¶¯»Ð§¹û£¬°üÀ¨ÎÄ×Ö·Å´óËõСÒÔ¼°ÑÕÉ«µÄ½¥±ä£»
4. ÔÚÅúÁ¿¸Ä±äÑ¡ÏîÖеÄÄÚÈÝʱ£¬¿ÉÒÔÑ¡ÔñÊÇ·ñ²ÉÓÃÓѺõĻ¬¶¯Ð§¹û£»
5. ¿ÉÒÔ¶¯Ì¬µÄÉèÖÃÊÇ·ñwrap£¬¼´£¬ÊÇ·ñÑ»·¹ö¶¯£»
6. Ñ¡ÖÐλÖÿÉÒÔÌí¼ÓÎÄ×Ö˵Ã÷£¬¿É¿ØÖÆÎÄ×Ö×ÖÌå´óСÑÕÉ«µÈ£»
7. ¾ßÓÐÔÚ´úÂëÖж¯Ì¬µÄ»¬¶¯µ½Ä³Ò»Î»ÖõŦÄÜ£»
8. Ö§³Öwrap_content£¬Ö§³ÖitemµÄpadding£»
9. Ìṩ¶àÖÖÊôÐÔ£¬ÓÅ»¯UIЧ¹û£»
10. ÔÚ»¬¶¯¹ý³ÌÖв»ÏìÓ¦onValueChanged()
11. µã»÷ÉÏϵ¥Ôª¸ñ£¬¿ÉÒÔ×Ô¶¯»¬¶¯µ½¶ÔÓ¦µÄµã»÷¶ÔÏó¡£
12. ¼æÈÝNumberPickerµÄÖØÒª·½·¨ºÍ½Ó¿Ú£º
//¼æÈݵķ½·¨ÓÐ:
setOnValueChangedListener()
setOnScrollListener()
setDisplayedValues()/getDisplayedValues()
setWrapSelectorWheel()/getWrapSelectorWheel()
setMinValue()/getMinValue()
setMaxValue()/getMaxValue()
setValue()/getValue()
//¼æÈݵÄÄÚ²¿»Øµ÷½Ó¿ÚÓУº
OnValueChangeListener
OnScrollListener
ʹÓ÷½·¨
1.µ¼ÈëÖÁ¹¤³Ì
compile 'cn.carbswang.android:NumberPickerView:1.0.2'
»òÕß
cn.carbswang.android
NumberPickerView
1.0.2
pom
2.ͨ¹ý²¼¾ÖÉùÃ÷NumberPickerView
<cn.carbswang.android.numberpickerview.library.NumberPickerView
android:id="@+id/picker"
android:layout_width="wrap_content"
android:layout_height="240dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:background="#11333333"
android:contentDescription="test_number_picker_view"
app:npv_ItemPaddingHorizental="5dp"
app:npv_ItemPaddingVertical="5dp"
app:npv_ShowCount="5"
app:npv_TextSizeNormal="16sp"
app:npv_TextSizeSelected="20sp"
app:npv_WrapSelectorWheel="true"/>
3.Java´úÂëÖÐʹÓãº
- ÈôÉèÖõÄÊý¾Ý(String[] mDisplayedValues)Ò»Ö±¹Ì¶¨²»»áÔٴθı䣬¿ÉÒÔʹÓÃÈçÏ·½Ê½½øÐÐÉèÖ㺣¨ÓëNumberPickerµÄÉèÖ÷½Ê½Ò»Ö£©
picker.setMinValue(minValue);
picker.setMaxValue(maxValue);
picker.setValue(value);
- ÈôÉèÖõÄÊý¾Ý(String[] mDisplayedValues)»á¸Ä±ä£¬¿ÉÒÔʹÓÃÈçÏÂ×éºÏ·½Ê½½øÐÐÉèÖ㺣¨ÓëNumberPickerµÄ¸ü¸ÄÊý¾Ý·½Ê½Ò»Ö£©
int minValue = getMinValue();
int oldMaxValue = getMaxValue();
int oldSpan = oldMaxValue - minValue + 1;
int newMaxValue = display.length - 1;
int newSpan = newMaxValue - minValue + 1;
if (newSpan > oldSpan) {
setDisplayedValues(display);
setMaxValue(newMaxValue);
} else {
setMaxValue(newMaxValue);
setDisplayedValues(display);
}
»òÕßÖ±½ÓʹÓÃNumberPickerViewÌṩµÄ·½·¨£º
refreshByNewDisplayedValues(String[] display)
ʹÓô˷½·¨Ê±ÐèҪעÒâ±£Ö¤Êý¾Ý¸Ä±äÇ°ºóµÄminValueÖµ²»±ä¡£
4.ÁíÍ⣬NumberPickerViewÌṩÁËƽ»¬¹ö¶¯µÄ·½·¨£º
public void smoothScrollToValue(int fromValue, int toValue, boolean needRespond)
´Ë·½·¨ÓësetValue(int)·½·¨Ïà֮ͬ´¦ÊÇ¿ÉÒÔ¶¯Ì¬ÉèÖõ±Ç°ÏÔʾµÄitem£¬²»Í¬Ö®´¦ÔÚÓÚ´Ë·½·¨¿ÉÒÔʹNumberPickerViewƽ»¬µÄ¹ö¶¯£¬¼´´ÓfromValueÖµÌôÑ¡×î½ü·¾¶¹ö¶¯µ½toValue¡£µÚÈý¸ö²ÎÊýneedRespondÓÃÀ´±êʶÔÚ»¬¶¯¹ý³ÌÖÐÊÇ·ñÏìÓ¦onValueChanged»Øµ÷º¯Êý£¬ÒòΪ¶à¸öNumberPickerViewÔÚÁª¶¯Ê±£¬ºÜ¿ÉÄܲ»Í¬µÄNumberPickerViewµÄֹͣʱ¼ä²»Í¬£¬Èç¹ûÔÚ´ËʱÏìÓ¦ÁËonValueChanged»Øµ÷£¬¾Í¿ÉÄÜÔÙ´ÎÁª¶¯£¬Ôì³ÉÊý¾Ý²»×¼È·£¬½«needRespondÖÃΪfalse£¬¿É±ÜÃâÔÚ»¬¶¯ÖÐÏìÓ¦»Øµ÷º¯Êý¡£
ÁíÍ⣬ÔÚʹÓô˷½·¨»òÕß¼ä½Óµ÷Óô˷½·¨Ê±£¬ÐèҪעÒâ×îºÃ²»ÒªÔÚonCreate(Bundle savedInstanceState)·½·¨Öе÷Óã¬ÒòΪscroll¶¯»ÐèÒªÒ»¶¨Ê±¼ä£¬ÈçÐèÈ·ÒªÔÚonCreate(Bundle savedInstanceState)Öе÷Óã¬ÇëʹÓÃÈçÏ·½Ê½£º
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//´úÂëÊ¡ÂÔ
mNumberPickerView.post(new Runnable() {
@Override
public void run() {
//µ÷ÓÃsmoothScrollToValue()µÈ·½·¨µÄ´úÂë
}
});
½«NumberPicker¸ÄΪNumberPickerView
ÒªÌæ´úÏîÄ¿ÖÐʹÓõÄNumberPicker£¬Ö»ÐèÒª½«Éæ¼°NumberPickerµÄ´úÂ루Èç»Øµ÷Öд«ÈëÁËNumberPicker¡¢Ê¹ÓÃÁËNumberPickerµÄÄÚ²¿½Ó¿Ú£©¸ÄΪNumberPickerView¼´¿É¡£
¸÷Ïî×Ô¶¨ÒåÊôÐÔµÄ˵Ã÷
<attr name="npv_ShowCount"format="reference|integer"/>//ÏÔʾµÄÌõÄ¿¸öÊý£¬Ä¬ÈÏ3¸ö
<attr name="npv_ShowDivider"format="reference|boolean"/>//ÊÇ·ñÏÔʾÁ½Ìõdivider£¬Ä¬ÈÏÏÔʾ
<attr name="npv_DividerColor"format="reference|color"/>//Á½ÌõdividerµÄÑÕÉ«
<attr name="npv_DividerMarginLeft"format="reference|dimension"/>//divider¾à×ó²àµÄ¾àÀë
<attr name="npv_DividerMarginRight"format="reference|dimension"/>//divider¾àÓÒ²àµÄ¾àÀë
<attr name="npv_DividerHeight"format="reference|dimension"/>//dividerµÄ¸ß¶È
<attr name="npv_TextColorNormal"format="reference|color"/>//δѡÖÐÎÄ×ÖµÄÑÕÉ«
<attr name="npv_TextColorSelected"format="reference|color"/>//Ñ¡ÖÐÎÄ×ÖµÄÑÕÉ«
<attr name="npv_TextColorHint"format="reference|color"/>//ÖмäÆ«ÓÒ²à˵Ã÷ÎÄ×ÖµÄÑÕÉ«
<attr name="npv_TextSizeNormal"format="reference|dimension"/>//δѡÖÐÎÄ×ֵĴóС
<attr name="npv_TextSizeSelected"format="reference|dimension"/>//Ñ¡ÖÐÎÄ×ֵĴóС
<attr name="npv_TextSizeHint"format="reference|dimension"/>//˵Ã÷ÎÄ×ֵĴóС
<attr name="npv_TextArray"format="reference"/>//ÎÄ×ÖÄÚÈÝ£¬stringarrayÀàÐÍ
<attr name="npv_MinValue"format="reference|integer"/>//×îСֵ£¬Í¬setMinValue()
<attr name="npv_MaxValue"format="reference|integer"/>//×î´óÖµ£¬Í¬setMaxValue()
<attr name="npv_WrapSelectorWheel"format="reference|boolean"/>//ÉèÖÃÊÇ·ñwrap£¬Í¬setWrapSelectorWheel
<attr name="npv_HintText"format="reference|string"/>//ÉèÖÃ˵Ã÷ÎÄ×Ö
<attr name="npv_EmptyItemHint"format="reference|string"/>//¿ÕÐеÄÏÔʾÎÄ×Ö£¬Ä¬Èϲ»ÏÔʾÈκÎÎÄ×Ö¡£Ö»ÔÚWrapSelectorWheel==falseÊÇÆð×÷ÓÃ
<attr name="npv_MarginStartOfHint"format="reference|dimension"/>//˵Ã÷ÎÄ×Ö¾àÀë×ó²àµÄ¾àÀ룬"×ó²à"ÊÇÖ¸ÎÄ×Öarray×î¿íitemµÄÓÒ²à
<attr name="npv_MarginEndOfHint"format="reference|dimension"/>//˵Ã÷ÎÄ×Ö¾àÀëÓÒ²àµÄ¾àÀë
<attr name="npv_ItemPaddingHorizental"format="reference|dimension"/>//itemµÄˮƽpadding£¬ÓÃÓÚwrap_contentģʽ
<attr name="npv_ItemPaddingVertical"format="reference|dimension"/>//itemµÄÊúÖ±padding£¬ÓÃÓÚwrap_contentģʽ
//ÒÔÏÂÊôÐÔÓÃÓÚÔÚwrap_contentģʽÏ£¬¸Ä±äÄÚÈÝarray²¢ÇÒÓÖ²»ÏëÈÿؼþ"Ìø¶¯"£¬ÄÇô¾Í¿ÉÒÔÉèÖÃËùÓиıäµÄÄÚÈݵÄ×î´ó¿í¶È
<attr name="npv_AlternativeTextArrayWithMeasureHint"format="reference"/>//¿ÉÄÜ´ïµ½µÄ×î´ó¿í¶È£¬°üÀ¨ËµÃ÷ÎÄ×ÖÔÚÄÚ£¬×î´ó¿í¶ÈÖ»¿ÉÄܱȴËStringµÄ¿í¶È¸ü´ó
<attr name="npv_AlternativeTextArrayWithoutMeasureHint"format="reference"/>//¿ÉÄÜ´ïµ½µÄ×î´ó¿í¶È£¬²»°üÀ¨ËµÃ÷ÎÄ×ÖÔÚÄÚ£¬×î´ó¿í¶ÈÖ»¿ÉÄܱȴËStringµÄ¿í¶È+˵Ã÷ÎÄ×Ö+˵Ã÷ÎÄ×Ömarginstart +˵Ã÷ÎÄ×Ömarginend ¸ü´ó
<attr name="npv_AlternativeHint"format="reference|string"/>//˵Ã÷ÎÄ×ÖµÄ×î´ó¿í¶È
Ö÷ÒªÔÀí
Ò»°ãÇé¿öÏ£¬ÎÒÃÇֻʹÓÃNumberPicker¶ÔÎÄ×Ö½øÐÐÑ¡Ôñ£¬ºÜÉÙÉæ¼°µ½Ìí¼Ó²»Í¬µÄViewÉõÖÁÊÇͼƬ£¬Òò´Ë£¬NumberPickerViewÖ»Õë¶Ô´«ÈëµÄString[] ÀàÐ͵ÄÄÚÈÝͨ¹ýonDraw(Canvas canvas)º¯Êý½øÐÐÏÔʾ¡£
ÕâÀïÖ÷ÒªÉæ¼°Èý¸ö֪ʶµã£º
1.¹ö¶¯Ð§¹ûµÄ²úÉú£º
AndroidµÄframeworkÖдøÓÐÒ»¸ö¹¤¾ßÀàScroller£¬´ËÀàµÄ¹¦ÄÜÊǸù¾ÝÊäÈëÖµÒÔ¼°µ±Ç°³ÖÐøµÄʱ¼ä£¬ÅäºÏ²åÖµ¼ÆËãÆ÷£¬¼ÆËã³öµ±Ç°µÄÊä³öÖµ¡£ÊäÈëÖµÒ»°ãÊÇËٶȺÍ×ø±êÖµ£¬Êä³öÖµÊÇ×ø±êÖµ£¬¾ÙÀýÀ´Ëµ£¬¿ÉÒÔ½«ÆäÏëÏñ³É¸ßÖÐÎïÀí¸ù¾Ý³õʼËٶȡ¢¼ÓËٶȺÍÔËÐÐʱ¼äÇóÈ¡µ±Ç°Â·³Ì¡£ScrollerµÄʵÏֱȽÏÇÉÃËü²»»áÔÚstartScroll()ºóÈ¥¼ÆË㵱ǰ¡°Â·³Ì¡±£¬¶øÊÇÖ»¼Ç¼¡°³ö·¢¡±Ê±µÄ¸÷ÖÖ״̬£¬Ö»Óе±ÍⲿÐèÒªÖªµÀ´Ëʱ»¬¶¯µ½µÄλÖÃʱ£¬²Å»áÈ¥¸ù¾Ýʱ¼äÒÔ¼°²åÖµÀ´½øÐмÆË㣬ÕâÖÖÉè¼Æ±ÜÃâÁËÁíÆðÏß³Ìʵʱ¼ÆËãµÈÎÊÌâ¡£ÄÇôÎÊÌâÀ´ÁË£¬Ê²Ã´Ê±ºòÈ¥»ñÈ¡scrollerÖе±Ç°µÄ×ø±êÖµÄØ£¿ÔĶÁViewÀàµÄÔ´Â룬ÎÒÃÇ¿ÉÒÔ¿´µ½ÔÚViewµÄboolean draw(Canvas canvas, ViewGroup parent, long drawingTime)º¯ÊýÖУ¬ÓÐÈçÏ´úÂ룺
if (!drawingWithRenderNode) {
computeScroll();
sx = mScrollX;
sy = mScrollY;
}
¼´ÔÚ»æÖÆviewʱ£¬Ïȵ÷ÓÃcomputeScroll()£¬Òò´ËÎÒÃÇ¿ÉÒÔÔÚcomputeScroll()º¯ÊýÖØÐÂÉèÖûòˢе±Ç°µÄ×ø±ê£¬²¢ÔÚonDraw(Canvas canvas)º¯ÊýÖиù¾Ýµ±Ç°µÄ״̬ÖØлæÖÆ´Ëview¡£computeScroll()µÄʹÓ÷½·¨Í¨³£Îª£º
@Override
public void computeScroll() {
//Èç¹ûScrollerÈÔÈ»ÔÚ¹ö¶¯
if (mScroller.computeScrollOffset()) {
//»ñÈ¡mScrollerÖеÄÖµ²¢¼ÆËãºÍ¼Ç¼£¬Èç mGlobalY = mScroller.getCurrY();
//Ë¢ÐÂ
postInvalidate();
}
ÔÚNumberPickerViewÖУ¬ÎÒʹÓÃÒ»¸öglobalYÖµÀ´¼Ç¼µ±Ç°¹ö¶¯µ½µÄ×ø±ê£¬²¢Í¨¹ýÓëItemµÄ¸ß¶ÈÏà³ý£¬¼ÆË㵱ǰӦ¸ÃÏÔʾµÄitemµÄÆ«ÒÆÖµ£¬´Ó¶ø»³öµ±Ç°Ö»ÔÚÏÔʾÇøÓòµÄitem¡£»æÖƵÄ˼·Ã÷È·ÁË£¬ÔÙÀ´¿´»¬¶¯¸úËæÊÖÖ¸Òƶ¯ÒÔ¼°flingЧ¹û¡£ÕâÁ½Õß¾ùÊÇͨ¹ýoverrideonTouchEvent(MotionEvent event)º¯ÊýÀ´ÊµÏֵģ¬²»¹ýʵÏֵľßÌå¹ý³ÌÉÔÓв»Í¬£º
(1). ¸úËæÊÖÖ¸»¬¶¯ÊǸ´Ð´ÁËMotionEvent.ACTION_MOVEµÄÇé¿ö£¬¸ù¾Ýµ±Ç°ÊÖÖ¸Òƶ¯µÄ×ø±êÖµ£¬¼ÆËãglobalYÖµ£¬²¢Ë¢ÐÂÏÔʾ¡£
(2). flingЧ¹ûÊÇͨ¹ýVelocityTracker¹¤¾ßÀàʵÏֵģ¬´Ë¹¤¾ßÀà¿ÉÒÔ¸ù¾Ý½ÓÊÕµÄÁ½¸öÁ¬Ðø·¢³öµÄMotionEventÀ´»ñÈ¡µ±Ç°µÄ»¬¶¯Ëٶȣ¬ÈôËٶȴóÓÚãÐÖµ£¬Ôò½«³õʼ×ø±êÖµ¡¢VelocityTracker¼ÆËã»ñÈ¡µÄËٶȴ«µÝ¸øScroller.fling(...)º¯Êý£¬´ËʱÔÙ´ÎˢУ¬¼´¿Éͨ¹ýcomputeScroll()º¯Êý£¬»ñÈ¡µ±Ç°globalYÖµ£¬½ø¶ø¸üлæͼ¡£
2.×Ô¶¯Ð£×¼Î»ÖÃ
ΪÁËʵÏÖ×Ô¶¯Ð£×¼£¬ÎÒÔÚÿ´ÎÊÖÖ¸Up»òÕßScroller¿ªÊ¼Flingʱ£¬¾ùͨ¹ýhandler·¢ËÍrefreshÏûÏ¢£¬ÔÚ½ÓÊܵ½´ËÏûϢʱ£¬¼ÆË㵱ǰλÖÃÊÇ·ñ´¦ÓÚ±»Ð£×¼µÄλÖã¬Èç¹û·ñ£¬Ôò¼ÆËãÐèÒª»¬¶¯µÄλÒÆ£¬²¢½«Öµ´«µÝ¸øScroller£¬½ø¶ø½øÐÐУ׼»¬¶¯¡£µ±È·±£ÒѾУ׼ºó£¬ÔÝÍ£·¢ËÍrefreshÏûÏ¢¡£
3.½¥±äµÄUIЧ¹û
½¥±äUIЧ¹ûͬÑùÊÇͨ¹ý¼ÆË㵱ǰ»¬¶¯µÄ×ø±êÒÔ¼°Ä³¸öitemÓëÖмäÏÔʾλÖõIJîÖµ±ÈÀý£¬À´È·¶¨´ËitemÖеÄ×ÖÌå´óСÒÔ¼°ÑÕÉ«¡£
½«NumberPicker¸ÄΪNumberPickerView
ÒªÌæ´úÏîÄ¿ÖÐʹÓõÄNumberPicker£¬Ö»ÐèÒª½«Éæ¼°NumberPickerµÄ´úÂ루Èç»Øµ÷Öд«ÈëÁËNumberPicker¡¢Ê¹ÓÃÁËNumberPickerµÄÄÚ²¿½Ó¿Ú£©¸ÄΪNumberPickerView¼´¿É¡£
ÏîÄ¿µØÖ·
https://github.com/Carbs0126/NumberPickerView
»¶Ó´ó¼ÒÖ¸½Ì¡£email:yeah0126@yeah.net