本文实例为大家分享了Android实现自定义日期选择器的具体代码,供大家参考,具体内容如下
项目要求效果图:
要求 “6月20 星期五” 这一项作为一个整体可以滑动,”7时”、”48分”分别作为一个滑动整体。
系统自带的DatePicker、TimePicker大家都知道,只有这种效果:
百度了很多,试了NumberPicker等都不行,本来打算自己写。网友推荐了一个开源组件WheelView,下下来试了试,发现他已经定义的很完善了,在他的基础上拓展很容易。
现将基于wheelView自定义日期选择器记录如下:
一.首先要了解WheelView为我们提供了什么:
除了我写的”DateObject”与”StringWheelAdapter”,其余都是WheelView提供的,
1. WheelView.java :可滚动的组件
主要方法:
1
2
3
4setAdapter(new StringWheelAdapter(dateList, 7)); //设置Adapter setVisibleItems(3); //设置显示几行数据 setCyclic(true); //设置是否循环显示数据 addChangingListener(onDaysChangedListener) //设置滑动监听器
2. WheelAdapter.java : 滑动组件的适配器的接口,子类适配器用于装载数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23public interface WheelAdapter { /** * Gets items count * @return the count of wheel items */ public int getItemsCount(); /** * Gets a wheel item by index. * * @param index the item index * @return the wheel item text or null */ public String getItem(int index); /** * Gets maximum item length. It is used to determine the wheel width. * If -1 is returned there will be used the default wheel width. * * @return the maximum item length or -1 */ public int getMaximumLength(); }
3. OnWheelChangedListener.java : 滑动监听器接口
1
2
3
4
5
6
7
8
9public interface OnWheelChangedListener { /** * Callback method to be invoked when current item changed * @param wheel the wheel view whose state has changed * @param oldValue the old value of current item * @param newValue the new value of current item */ void onChanged(WheelView wheel, int oldValue, int newValue); }
4.OnWheelScrollListener.java :滚动监听器接口(暂时没用到)
5.NumericWheelAdapter.java : 当滚动内容为纯数字时调用的适配器
6.DateObject.java : 日期实体类,用于存储、获取选择的数据
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150package kankan.wheel.widget; import java.util.Calendar; public class DateObject extends Object{ private int year ; private int month; private int day; private int week; private int hour; private int minute; private String listItem; /** * 日期对象的4个参数构造器,用于设置日期 * @param year * @param month * @param day * @author sxzhang */ public DateObject(int year2, int month2, int day2,int week2) { super(); this.year = year2; int maxDayOfMonth = Calendar.getInstance().getActualMaximum(Calendar.DAY_OF_MONTH); if(day2 > maxDayOfMonth){ this.month = month2 + 1; this.day = day2 % maxDayOfMonth; }else{ this.month = month2; this.day = day2; } this.week = week2 % 7 == 0 ? 7 : week2 % 7; if(day == Calendar.getInstance().get(Calendar.DAY_OF_MONTH)){ this.listItem = String.format("%02d", this.month) +"月" + String.format("%02d", this.day) + "日 "+ " 今天 "; }else{ this.listItem = String.format("%02d", this.month) +"月" + String.format("%02d", this.day) + "日 "+ getDayOfWeekCN(week); } } /** * 日期对象的2个参数构造器,用于设置时间 * @param hour2 * @param minute2 * @param isHourType true:传入的是hour; false: 传入的是minute * @author sxzhang */ public DateObject(int hour2,int minute2,boolean isHourType) { super(); if(isHourType == true && hour2 != -1){ //设置小时 if(hour2 > 24){ this.hour = hour2 % 24; }else this.hour = hour2; this.listItem = this.hour + "时"; }else if(isHourType == false && minute2 != -1){ //设置分钟 if(minute2 > 60) this.minute = minute2 % 60; else this.minute = minute2; this.listItem = this.minute + "分"; } } public int getHour() { return hour; } public void setHour(int hour) { this.hour = hour; } public int getMinute() { return minute; } public void setMinute(int minute) { this.minute = minute; } public int getWeek() { return week; } public void setWeek(int week) { this.week = week; } public int getYear() { return year; } public void setYear(int year) { this.year = year; } public int getMonth() { return month; } public void setMonth(int month) { this.month = month; } public int getDay() { return day; } public void setDay(int day) { this.day = day; } public String getListItem() { return listItem; } public void setListItem(String listItem) { this.listItem = listItem; } /** * 根据day_of_week得到汉字星期 * @return */ public static String getDayOfWeekCN(int day_of_week){ String result = null; switch(day_of_week){ case 1: result = "星期日"; break; case 2: result = "星期一"; break; case 3: result = "星期二"; break; case 4: result = "星期三"; break; case 5: result = "星期四"; break; case 6: result = "星期五"; break; case 7: result = "星期六"; break; default: break; } return result; } }
7.StringWheelAdapter.java :一会儿将定义的滚动内容为字符串的适配器,当内容为字符串时我们就可以随意拓展滑动部分的内容
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
49package kankan.wheel.widget; import java.util.ArrayList; /** * The simple String Array wheel adapter * */ public class StringWheelAdapter implements WheelAdapter { /** The default items length */ public static final int DEFAULT_LENGTH = -1; // items private ArrayList<DateObject> list; // length private int length; /** * Constructor * @param items the items * @param length the max items length */ public StringWheelAdapter(ArrayList<DateObject> list, int length) { this.list = list; this.length = length; } @Override public String getItem(int index) { if (index >= 0 && index < list.size()) { return list.get(index).getListItem(); } return null; } @Override public int getItemsCount() { return list.size(); } @Override public int getMaximumLength() { return length; } }
二.了解以后就可以使用他定义我们需要的了。
1.首先要做的是这个效果的部分:
我们将其命名为DatePicker:
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143package com.sxkeji.timeswitch.widget; import java.util.ArrayList; import java.util.Calendar; import kankan.wheel.widget.DateObject; import kankan.wheel.widget.OnWheelChangedListener; import kankan.wheel.widget.StringWheelAdapter; import kankan.wheel.widget.WheelView; import android.content.Context; import android.util.AttributeSet; import android.widget.LinearLayout; /** * 自定义的日期选择器 * @author sxzhang * */ public class DatePicker extends LinearLayout { private Calendar calendar = Calendar.getInstance(); private WheelView newDays; private ArrayList<DateObject> dateList ; private OnChangeListener onChangeListener; //onChangeListener private final int MARGIN_RIGHT = 20; private DateObject dateObject; //日期数据对象 //Constructors public DatePicker(Context context) { super(context); init(context); } public DatePicker(Context context, AttributeSet attrs) { super(context, attrs); init(context); } /** * 初始化 * @param context */ private void init(Context context){ int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH) + 1; int day = calendar.get(Calendar.DAY_OF_MONTH); int week = calendar.get(Calendar.DAY_OF_WEEK); dateList = new ArrayList<DateObject>(); for (int i = 0; i < 7; i++) { dateObject = new DateObject(year, month, day+i, week+i); dateList.add(dateObject); } newDays = new WheelView(context); LayoutParams newDays_param = new LayoutParams(300,LayoutParams.WRAP_CONTENT); newDays_param.setMargins(0, 0, MARGIN_RIGHT, 0); newDays.setLayoutParams(newDays_param); newDays.setAdapter(new StringWheelAdapter(dateList, 7)); newDays.setVisibleItems(3); newDays.setCyclic(true); newDays.addChangingListener(onDaysChangedListener); addView(newDays); } /** * 滑动改变监听器 */ private OnWheelChangedListener onDaysChangedListener = new OnWheelChangedListener(){ @Override public void onChanged(WheelView mins, int oldValue, int newValue) { calendar.set(Calendar.DAY_OF_MONTH, newValue + 1); change(); } }; /** * 滑动改变监听器回调的接口 */ public interface OnChangeListener { void onChange(int year, int month, int day, int day_of_week); } /** * 设置滑动改变监听器 * @param onChangeListener */ public void setOnChangeListener(OnChangeListener onChangeListener){ this.onChangeListener = onChangeListener; } /** * 滑动最终调用的方法 */ private void change(){ if(onChangeListener!=null){ onChangeListener.onChange( dateList.get(newDays.getCurrentItem()).getYear(), dateList.get(newDays.getCurrentItem()).getMonth(), dateList.get(newDays.getCurrentItem()).getDay(), dateList.get(newDays.getCurrentItem()).getWeek()); } } /** * 根据day_of_week得到汉字星期 * @return */ public static String getDayOfWeekCN(int day_of_week){ String result = null; switch(day_of_week){ case 1: result = "星期日"; break; case 2: result = "星期一"; break; case 3: result = "星期二"; break; case 4: result = "星期三"; break; case 5: result = "星期四"; break; case 6: result = "星期五"; break; case 7: result = "星期六"; break; default: break; } return result; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }
2.然后要做的是这个效果的部分
我们命名为TimePicker:
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142package com.sxkeji.timeswitch.widget; import java.util.ArrayList; import java.util.Calendar; import kankan.wheel.widget.DateObject; import kankan.wheel.widget.OnWheelChangedListener; import kankan.wheel.widget.StringWheelAdapter; import kankan.wheel.widget.WheelView; import android.content.Context; import android.util.AttributeSet; import android.widget.LinearLayout; /** * 自定义的时间选择器 * @author sxzhang * */ public class TimePicker extends LinearLayout{ private Calendar calendar = Calendar.getInstance(); private WheelView hours, mins; //Wheel picker private OnChangeListener onChangeListener; //onChangeListener private final int MARGIN_RIGHT = 15; //调整文字右端距离 private ArrayList<DateObject> hourList,minuteList; private DateObject dateObject; //时间数据对象 //Constructors public TimePicker(Context context) { super(context); init(context); } public TimePicker(Context context, AttributeSet attrs) { super(context, attrs); init(context); } /** * 初始化 * @param context */ private void init(Context context){ int hour = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE); hourList = new ArrayList<DateObject>(); minuteList = new ArrayList<DateObject>(); for (int i = 0; i < 24; i++) { dateObject = new DateObject(hour+i,-1,true); hourList.add(dateObject); } for (int j = 0; j < 60; j++) { dateObject = new DateObject(-1,minute+j,false); minuteList.add(dateObject); } //小时选择器 hours = new WheelView(context); LayoutParams lparams_hours = new LayoutParams(80,LayoutParams.WRAP_CONTENT); lparams_hours.setMargins(0, 0, MARGIN_RIGHT, 0); hours.setLayoutParams(lparams_hours); hours.setAdapter(new StringWheelAdapter(hourList, 24)); hours.setVisibleItems(3); hours.setCyclic(true); hours.addChangingListener(onHoursChangedListener); addView(hours); //分钟选择器 mins = new WheelView(context); mins.setLayoutParams(new LayoutParams(80,LayoutParams.WRAP_CONTENT)); mins.setAdapter(new StringWheelAdapter(minuteList,60)); mins.setVisibleItems(3); mins.setCyclic(true); mins.addChangingListener(onMinsChangedListener); addView(mins); } //listeners private OnWheelChangedListener onHoursChangedListener = new OnWheelChangedListener(){ @Override public void onChanged(WheelView hours, int oldValue, int newValue) { calendar.set(Calendar.HOUR_OF_DAY, newValue); change(); } }; private OnWheelChangedListener onMinsChangedListener = new OnWheelChangedListener(){ @Override public void onChanged(WheelView mins, int oldValue, int newValue) { calendar.set(Calendar.MINUTE, newValue); change(); } }; /** * 滑动改变监听器回调的接口 */ public interface OnChangeListener { void onChange(int hour, int munite); } /** * 设置滑动改变监听器 * @param onChangeListener */ public void setOnChangeListener(OnChangeListener onChangeListener){ this.onChangeListener = onChangeListener; } /** * 滑动最终调用的方法 */ private void change(){ if(onChangeListener!=null){ onChangeListener.onChange(getHourOfDay(), getMinute()); } } /** * 获取小时 * @return */ public int getHourOfDay(){ return hourList.get(hours.getCurrentItem()).getHour(); } /** * 获取分钟 * @return */ public int getMinute(){ return minuteList.get(mins.getCurrentItem()).getMinute(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }
3.最后就可以直接使用了,我这里主界面是一个button,点击后弹出popupWindow显示日期选择器。布局文件及主Activity如下:
popupWindow布局文件:
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<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:background="#FFF"> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#f5f5f5"/> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="10dp"> <TextView android:id="@+id/tv_cancel" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="取消" android:layout_marginLeft="10dp" android:layout_alignParentLeft="true" android:textColor="#000000" android:textSize="20sp" /> <TextView android:id="@+id/tv_ok" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="确定" android:layout_marginRight="10dp" android:layout_alignParentRight="true" android:textColor="#000000" android:textSize="20sp" /> </RelativeLayout> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#f5f5f5"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginTop="10dp" android:padding="20dp"> <com.sxkeji.timeswitch.widget.DatePicker android:id="@+id/dp_test" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="3" android:gravity="center" android:layout_gravity="center_horizontal"/> <com.sxkeji.timeswitch.widget.TimePicker android:id="@+id/tp_test" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" android:gravity="center" android:layout_gravity="center_horizontal"/> </LinearLayout> </LinearLayout>
主界面布局文件:
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<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#FFF" android:id="@+id/Rl_all"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_alignParentBottom="true" android:padding="10dp" android:gravity="center"> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#f5f5f5"/> <Button android:id="@+id/btn_naozhong" android:layout_width="30dp" android:layout_height="30dp" android:background="@drawable/naozhong" /> </LinearLayout> </RelativeLayout>
Activity代码:
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122package com.sxkeji.timeswitch.activity; import java.util.Calendar; import org.unism.wang.R; import com.sxkeji.timeswitch.widget.DatePicker; import com.sxkeji.timeswitch.widget.TimePicker; import android.app.Activity; import android.os.Bundle; import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.LinearLayout; import android.widget.PopupWindow; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; /** * 主页面 * @author sxzhang */ public class MyPickerActivity extends Activity { private Calendar calendar; private DatePicker dp_test; private TimePicker tp_test; private TextView tv_ok,tv_cancel; //确定、取消button private Button btn_naozhong; private PopupWindow pw; private String selectDate,selectTime; //选择时间与当前时间,用于判断用户选择的是否是以前的时间 private int currentHour,currentMinute,currentDay,selectHour,selectMinute,selectDay; //整体布局 private RelativeLayout Rl_all; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Rl_all = (RelativeLayout) findViewById(R.id.Rl_all); btn_naozhong = (Button) findViewById(R.id.btn_naozhong); calendar = Calendar.getInstance(); btn_naozhong.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { View view = View.inflate(MyPickerActivity.this, R.layout.dialog_select_time, null); selectDate = calendar.get(Calendar.YEAR) + "年" + calendar.get(Calendar.MONTH) + "月" + calendar.get(Calendar.DAY_OF_MONTH) + "日" + DatePicker.getDayOfWeekCN(calendar.get(Calendar.DAY_OF_WEEK)); //选择时间与当前时间的初始化,用于判断用户选择的是否是以前的时间,如果是,弹出toss提示不能选择过去的时间 selectDay = currentDay = calendar.get(Calendar.DAY_OF_MONTH); selectMinute = currentMinute = calendar.get(Calendar.MINUTE); selectHour = currentHour = calendar.get(Calendar.HOUR_OF_DAY); selectTime = currentHour + "点" + ((currentMinute < 10)?("0"+currentMinute):currentMinute) + "分"; dp_test = (DatePicker)view.findViewById(R.id.dp_test); tp_test = (TimePicker)view.findViewById(R.id.tp_test); tv_ok = (TextView) view.findViewById(R.id.tv_ok); tv_cancel = (TextView) view.findViewById(R.id.tv_cancel); //设置滑动改变监听器 dp_test.setOnChangeListener(dp_onchanghelistener); tp_test.setOnChangeListener(tp_onchanghelistener); pw = new PopupWindow(view, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, true); // //设置这2个使得点击pop以外区域可以去除pop // pw.setOutsideTouchable(true); // pw.setBackgroundDrawable(new BitmapDrawable()); //出现在布局底端 pw.showAtLocation(Rl_all, 0, 0, Gravity.END); //点击确定 tv_ok.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { if(selectDay == currentDay ){ //在当前日期情况下可能出现选中过去时间的情况 if(selectHour < currentHour){ Toast.makeText(getApplicationContext(), "不能选择过去的时间n 请重新选择", 0).show(); }else if( (selectHour == currentHour) && (selectMinute < currentMinute) ){ Toast.makeText(getApplicationContext(), "不能选择过去的时间n 请重新选择", 0).show(); }else{ Toast.makeText(getApplicationContext(), selectDate+selectTime, 0).show(); pw.dismiss(); } }else{ Toast.makeText(getApplicationContext(), selectDate+selectTime, 0).show(); pw.dismiss(); } } }); //点击取消 tv_cancel.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { pw.dismiss(); } }); } }); } //listeners DatePicker.OnChangeListener dp_onchanghelistener = new DatePicker.OnChangeListener() { @Override public void onChange(int year, int month, int day, int day_of_week) { selectDay = day; selectDate = year + "年" + month + "月" + day + "日" + DatePicker.getDayOfWeekCN(day_of_week); } }; TimePicker.OnChangeListener tp_onchanghelistener = new TimePicker.OnChangeListener() { @Override public void onChange(int hour, int minute) { selectTime = hour + "点" + ((minute < 10)?("0"+minute):minute) + "分"; selectHour = hour; selectMinute = minute; } }; }
最终效果图:
源码下载:Android实现自定义日期选择器
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持靠谱客。
最后
以上就是专注龙猫最近收集整理的关于Android基于wheelView实现自定义日期选择器的全部内容,更多相关Android基于wheelView实现自定义日期选择器内容请搜索靠谱客的其他文章。
发表评论 取消回复