更新:
通过为TimePicker控件增加属性,使其具有是否以当前时间为上限的属性设置。
1、在attrs.xml文件中增加:
name="TimePicker">
name="Timelimited" format="boolean"/>
2、在需要使用TimePicker控件的xml中设置:
xmlns:timePicker="http://schemas.android.com/apk/res-auto"并在控件处使用:
android:id="@+id/datepicker_start"
timePicker:Timelimited="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
这样我们就能在TimePicker的构造函数中获取该属性并根据其值做相应操作:
比如下面的 flag 就是我们上面设置的属性值;
public TimePicker(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TimePicker); boolean flag = a.getBoolean(R.styleable.TimePicker_Timelimited,false); LayoutInflater.from(context).inflate(R.layout.pickerview_time, this,true);//这是对上面两句的包装。 final View timepickerview = findViewById(R.id.timepicker); wheelTime = new WheelTime(timepickerview, TimePickerType.Type.YEAR_MONTH_DAY); if (!flag){ int endYear=a.getInt(R.styleable.TimePicker_endYear,2900); wheelTime.setEndYear(endYear); }
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
最近手上的项目要求弄一个包含两个日期选择控件的UI界面(即开始时间和结束时间)。
一、
一开始就想到使用自带的DatePicker控件。但是发现其UI很难调整到项目想要的效果。尤其是其与项目theme的关系,在xml中设置style也不好使。从Popwindow到AlertDialog都试过了,只有含单个DatePicker的DateAlertDialog还比较赏心悦目,却不满足项目需要。
于是决定用自定义DatePicker来实现。
通过一番波折,自己实现了大部分功能,但对日期的年月日的配合调整的不是很好。
无意间在网上发现了Pickerview这个开源项目。(地址:https://github.com/saiwu-bigkoo/Android-PickerView#demo-图片)其中的TimePickerView比较符合我的需求,就借来稍加改动,使用了起来。
二、
由于TimePickerView的不是传统意义上的控件,其使用方式比较固定,不方便。我稍加改动,创建了TimePicker控件。
该控件的功能是:提供年月日用于选择,可选范围是:1990年1月1日到当前时间。 通过getTime()可以获取用户选择的时间。
代码:
1、Timepicker.java
public class TimePicker extends LinearLayout { WheelTime wheelTime; private OnTimeSelectListener timeSelectListener; public TimePicker(Context context) { super(context); } public TimePicker(Context context, AttributeSet attrs) { super(context, attrs); LayoutInflater.from(context).inflate(R.layout.pickerview_time, this,true);//这是对上面两句的包装。 final View timepickerview = findViewById(R.id.timepicker); wheelTime = new WheelTime(timepickerview, TimePickerType.Type.YEAR_MONTH_DAY); //默认选中当前时间 Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH); int day = calendar.get(Calendar.DAY_OF_MONTH); int hours = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE); wheelTime.setPicker(year, month, day, hours, minute); this.setClickable(true); this.setFocusable(true); } public Date getTime(){ String time= wheelTime.getTime(); Log.d("TimePicker","--------------getTime "+time); SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd"); Date d=new Date(); try { d=dateFormat.parse(time); } catch (ParseException e) { e.printStackTrace(); } return d; } /** * 设置可以选择的时间范围 * 要在setTime之前调用才有效果 * @param startYear 开始年份 * @param endYear 结束年份 */ public void setRange(int startYear, int endYear) { wheelTime.setStartYear(startYear); wheelTime.setEndYear(endYear); } /** * 设置选中时间 * @param date 时间 */ public void setTime(Date date) { Calendar calendar = Calendar.getInstance(); if (date == null) calendar.setTimeInMillis(System.currentTimeMillis()); else calendar.setTime(date); int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH); int day = calendar.get(Calendar.DAY_OF_MONTH); int hours = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE); wheelTime.setPicker(year, month, day, hours, minute); } // /** // * 指定选中的时间,显示选择器 // * // * @param date // */ // public void show(Date date) { // Calendar calendar = Calendar.getInstance(); // if (date == null) // calendar.setTimeInMillis(System.currentTimeMillis()); // else // calendar.setTime(date); // int year = calendar.get(Calendar.YEAR); // int month = calendar.get(Calendar.MONTH); // int day = calendar.get(Calendar.DAY_OF_MONTH); // int hours = calendar.get(Calendar.HOUR_OF_DAY); // int minute = calendar.get(Calendar.MINUTE); // wheelTime.setPicker(year, month, day, hours, minute); // show(); // } /** * 设置是否循环滚动 * @param cyclic 是否循环 */ public void setCyclic(boolean cyclic) { wheelTime.setCyclic(cyclic); } }
2、对应布局文件pickerview_time.xml
xml version="1.0" encoding="utf-8"?>xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> android:id="@+id/timepicker" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@android:color/white" android:orientation="horizontal"> android:id="@+id/year" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" /> android:id="@+id/month" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1.1" /> android:id="@+id/day" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1.1" /> android:id="@+id/hour" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1.1" /> android:id="@+id/min" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1.1" />
3、Wheeltime.java
public class WheelTime { public static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); private View view; private WheelView wv_year; private WheelView wv_month; private WheelView wv_day; private WheelView wv_hours; private WheelView wv_mins; private int year_now,month_now,day_now; private TimePickerType.Type type; public static final int DEFULT_START_YEAR = 1990; public static final int DEFULT_END_YEAR = 2100; private int startYear = DEFULT_START_YEAR; private int endYear = DEFULT_END_YEAR; public WheelTime(View view) { super(); this.view = view; type = TimePickerType.Type.ALL; setView(view); } public WheelTime(View view, TimePickerType.Type type) { super(); this.view = view; this.type = type; setView(view); } public void setPicker(int year, int month, int day) { this.setPicker(year, month, day, 0, 0); } public void setPicker(int year, int month, int day, int h, int m) { // 添加大小月月份并将其转换为list,方便之后的判断 String[] months_big = {"1", "3", "5", "7", "8", "10", "12"}; String[] months_little = {"4", "6", "9", "11"}; final Listlist_big = Arrays.asList(months_big); final List list_little = Arrays.asList(months_little); Context context = view.getContext(); // 年 wv_year = (WheelView) view.findViewById(R.id.year); wv_year.setAdapter(new NumericWheelAdapter(startYear, endYear));// 设置"年"的显示数据 wv_year.setLabel(context.getString(R.string.pickerview_year));// 添加文字 Log.d("WheelTime","-----------------year "+(year - startYear)); wv_year.setCurrentItem(year - startYear);// 初始化时显示的数据 // 月 wv_month = (WheelView) view.findViewById(R.id.month); wv_month.setAdapter(new NumericWheelAdapter(1, month_now)); wv_month.setLabel(context.getString(R.string.pickerview_month)); Log.d("WheelTime","-----------------month "+month); wv_month.setCurrentItem(month); // 日 wv_day = (WheelView) view.findViewById(R.id.day); // // 判断大小月及是否闰年,用来确定"日"的数据 // if (list_big.contains(String.valueOf(month + 1))) { // wv_day.setAdapter(new NumericWheelAdapter(1, 31)); // } else if (list_little.contains(String.valueOf(month + 1))) { // wv_day.setAdapter(new NumericWheelAdapter(1, 30)); // } else { // // 闰年 // if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) // wv_day.setAdapter(new NumericWheelAdapter(1, 29)); // else // wv_day.setAdapter(new NumericWheelAdapter(1, 28)); // } wv_day.setAdapter(new NumericWheelAdapter(1, day_now)); wv_day.setLabel(context.getString(R.string.pickerview_day)); Log.d("WheelTime","-----------------day "+day); wv_day.setCurrentItem(day - 1); wv_hours = (WheelView) view.findViewById(R.id.hour); wv_hours.setAdapter(new NumericWheelAdapter(0, 23)); wv_hours.setLabel(context.getString(R.string.pickerview_hours));// 添加文字 wv_hours.setCurrentItem(h); wv_mins = (WheelView) view.findViewById(R.id.min); wv_mins.setAdapter(new NumericWheelAdapter(0, 59)); wv_mins.setLabel(context.getString(R.string.pickerview_minutes));// 添加文字 wv_mins.setCurrentItem(m); // 添加"年"监听 OnItemSelectedListener wheelListener_year = new OnItemSelectedListener() { @Override public void onItemSelected(int index) { int year_num = index + startYear; // 判断大小月及是否闰年,用来确定"日"的数据 int maxItem = 30; if (list_big .contains(String.valueOf(wv_month.getCurrentItem() + 1))) { wv_day.setAdapter(new NumericWheelAdapter(1, 31)); maxItem = 31; } else if (list_little.contains(String.valueOf(wv_month .getCurrentItem() + 1))) { wv_day.setAdapter(new NumericWheelAdapter(1, 30)); maxItem = 30; } else { if ((year_num % 4 == 0 && year_num % 100 != 0) || year_num % 400 == 0) { wv_day.setAdapter(new NumericWheelAdapter(1, 29)); maxItem = 29; } else { wv_day.setAdapter(new NumericWheelAdapter(1, 28)); maxItem = 28; } } if (wv_day.getCurrentItem() > maxItem - 1) { wv_day.setCurrentItem(maxItem - 1); } if (year_num==year_now){ //今年最大的月份只能是当前月 wv_month.setAdapter(new NumericWheelAdapter(1, month_now)); }else { wv_month.setAdapter(new NumericWheelAdapter(1, 12)); } } }; // 添加"月"监听 OnItemSelectedListener wheelListener_month = new OnItemSelectedListener() { @Override public void onItemSelected(int index) { int month_num = index + 1; int maxItem = 30; // 判断大小月及是否闰年,用来确定"日"的数据 if (list_big.contains(String.valueOf(month_num))) { wv_day.setAdapter(new NumericWheelAdapter(1, 31)); maxItem = 31; } else if (list_little.contains(String.valueOf(month_num))) { wv_day.setAdapter(new NumericWheelAdapter(1, 30)); maxItem = 30; } else { if (((wv_year.getCurrentItem() + startYear) % 4 == 0 && (wv_year .getCurrentItem() + startYear) % 100 != 0) || (wv_year.getCurrentItem() + startYear) % 400 == 0) { wv_day.setAdapter(new NumericWheelAdapter(1, 29)); maxItem = 29; } else { wv_day.setAdapter(new NumericWheelAdapter(1, 28)); maxItem = 28; } } if (wv_day.getCurrentItem() > maxItem - 1) { wv_day.setCurrentItem(maxItem - 1); } if (month_num==month_now){ //今年最大的月份只能是当前月 wv_day.setAdapter(new NumericWheelAdapter(1, day_now)); } } }; wv_year.setOnItemSelectedListener(wheelListener_year); wv_month.setOnItemSelectedListener(wheelListener_month); // 根据屏幕密度来指定选择器字体的大小(不同屏幕可能不同) int textSize = 6; switch (type) { case ALL: textSize = textSize * 3; break; case YEAR_MONTH_DAY: textSize = textSize * 4; wv_hours.setVisibility(View.GONE); wv_mins.setVisibility(View.GONE); break; case HOURS_MINS: textSize = textSize * 4; wv_year.setVisibility(View.GONE); wv_month.setVisibility(View.GONE); wv_day.setVisibility(View.GONE); break; case MONTH_DAY_HOUR_MIN: textSize = textSize * 3; wv_year.setVisibility(View.GONE); break; case YEAR_MONTH: textSize = textSize * 4; wv_day.setVisibility(View.GONE); wv_hours.setVisibility(View.GONE); wv_mins.setVisibility(View.GONE); } wv_day.setTextSize(textSize); wv_month.setTextSize(textSize); wv_year.setTextSize(textSize); wv_hours.setTextSize(textSize); wv_mins.setTextSize(textSize); } /** * 设置是否循环滚动 * * @param cyclic */ public void setCyclic(boolean cyclic) { wv_year.setCyclic(cyclic); wv_month.setCyclic(cyclic); wv_day.setCyclic(cyclic); wv_hours.setCyclic(cyclic); wv_mins.setCyclic(cyclic); } public String getTime() { StringBuffer sb = new StringBuffer(); // sb.append((wv_year.getCurrentItem() + startYear)).append("-") // .append((wv_month.getCurrentItem() + 1)).append("-") // .append((wv_day.getCurrentItem() + 1)).append(" ") // .append(wv_hours.getCurrentItem()).append(":") // .append(wv_mins.getCurrentItem()); sb.append((wv_year.getCurrentItem() + startYear)).append("-") .append((wv_month.getCurrentItem() + 1)).append("-") .append((wv_day.getCurrentItem() + 1)); return sb.toString(); } public View getView() { return view; } public void setView(View view) { this.view = view; Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); year_now= calendar.get(Calendar.YEAR); month_now = calendar.get(Calendar.MONTH)+1; day_now = calendar.get(Calendar.DAY_OF_MONTH); int hours = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE); this.endYear=year_now; } public int getStartYear() { return startYear; } public void setStartYear(int startYear) { this.startYear = startYear; } public int getEndYear() { return endYear; } public void setEndYear(int endYear) { this.endYear = endYear; } }
提取出来的枚举类:
public class TimePickerType { public enum Type { ALL, YEAR_MONTH_DAY, HOURS_MINS, MONTH_DAY_HOUR_MIN , YEAR_MONTH }// 四种选择模式,年月日时分,年月日,时分,月日时分 }
效果图: