Android之DatePicker和TimePicker实现以及自定义大小

 关于日期和时间的几个相关控件,包括DatePicker(日期选择控件)、TimePicker(时间选择控件)、DatePickerDialog(日期选择对话框)、TimePickerDialog(时间选择对话框)、AnalogClock(模拟时钟控件)、DigitalClock(数字时钟控件)。

 DatePicker 、 TimePicker 都继承自android.widget.FrameLayout,并且默认展示风格、与操作风格也类似。DatePicker用于展示一个日期选择控件,TimePicker用于展示一个时间选择控件。

 作为一个日期选择控件,DatePicker可以通过设置属性来确定日期选择范围,也可以通过定义好的方法获取到当前选中的时间,并且在修改日期的时候,有响应的事件对其进行响应。

 DatePicker常用相关属性:

  • android:calendarViewShown:是否显示日历。
  • android:startYear:设置可选开始年份。
  • android:endYear:设置可选结束年份。
  • android:maxDate:设置可选最大日期,以mm/dd/yyyy格式设置。
  • android:minDate:设置可选最小日期,以mm/dd/yyyy格式设置。

 DatePicker的方法而言,除了常用获取属性的setter、getter方法之外,还需要特别注意一个初始化的方法init()方法,用于做DatePicker控件的初始化,并且设置日期被修改后,回调的响应事件。此方法的签名如下:

 init(int year, int monthOfYear, int dayOfMonth, DatePicker.OnDateChangedListener onDateChangedListener)

 从上面的init()方法可以看到,DatePicker被修改时响应的事件是DatePicker.OnDateChangedListener 事件,如果要响应此事件,需要实现其中的onDateChanged()方法,其中参数从签名即可了解意思,这里不再累述。

 onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth)

 作为一个时间选择控件来说,TimePicker需要与时间相关的getter、setter方法之外,还需要有时间被修改够,回调的响应事件。

 TimePicker常用方法有如下几个:

  • is24HourView():判断是否为24小时制。
  • setIs24HourView():设置是否为24小时制显示。
  • getCurrentXxx():获取当前时间。
  • setCurrentXxx():设置当前时间。
  • setOnTimeChangedListener():设置时间被修改的回调方法。

TimePicker控件被修改的回调方法,通过setOnTimeChangedListener()方法设置,其传递一个 TimePicker.OnTimeChangedListener 接口,需要实现其中的onTimeChanged()方法。


问题1:其实现思路就是自定义一个Dialog,然后往里面同时放入DatePicker和TimePicker,直接贴代码: 
date_time_picker.xml: 

Xml代码   收藏代码
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="wrap_content"  
  4.     android:layout_height="wrap_content"  
  5.     android:gravity="center"  
  6.     android:orientation="horizontal" >  
  7.   
  8.     <!-- <DatePicker  
  9.         android:id="@+id/new_act_date_picker"  
  10.         android:layout_width="0dip"  
  11.         android:layout_height="wrap_content"  
  12.         android:layout_weight="0.6"  
  13.         android:calendarViewShown="false" />  
  14.   
  15.     <TimePicker   
  16.         android:id="@+id/new_act_time_picker"  
  17.         android:layout_width="0dip"  
  18.         android:layout_height="wrap_content"  
  19.         android:layout_weight="0.3"/> -->  
  20.       
  21.     <DatePicker  
  22.         android:id="@+id/new_act_date_picker"  
  23.         android:layout_width="wrap_content"  
  24.         android:layout_height="wrap_content"  
  25.         android:calendarViewShown="false" />  
  26.   
  27.     <TimePicker   
  28.         android:id="@+id/new_act_time_picker"  
  29.         android:layout_width="wrap_content"  
  30.         android:layout_height="wrap_content"/>  
  31.   
  32. </LinearLayout>  
然后在需要显示日期时间选择器的地方(一般是一个onClickListener中)实例化dialog: 
DemoActivity.java 
Java代码   收藏代码
  1. arriveAtBtn.setOnClickListener(new View.OnClickListener(){  
  2.             @SuppressLint("NewApi")  
  3.             @Override  
  4.             public void onClick(View v) {  
  5.                 View view = View.inflate(getApplicationContext(), R.layout.date_time_picker, null);  
  6.                 final DatePicker datePicker = (DatePicker)view.findViewById(R.id.new_act_date_picker);  
  7.                 final TimePicker timePicker = (TimePicker)view.findViewById(R.id.new_act_time_picker);  
  8.                   
  9.                 // Init DatePicker  
  10.                 int year;  
  11.                 int month;  
  12.                 int day;  
  13.                 if (StringUtils.isEmpty(arriveDateBtn.getText().toString())) {  
  14.                     // Use the current date as the default date in the picker  
  15.                     final Calendar c = Calendar.getInstance();  
  16.                     year = c.get(Calendar.YEAR);  
  17.                     month = c.get(Calendar.MONTH);  
  18.                     day = c.get(Calendar.DAY_OF_MONTH);  
  19.                 } else {  
  20.                     year = NewActActivity.arrive_year;  
  21.                     month = NewActActivity.arrive_month;  
  22.                     day = NewActActivity.arrive_day;  
  23.                 }  
  24.                 datePicker.init(year, month, day, null);  
  25.                   
  26.                 // Init TimePicker  
  27.                 int hour;  
  28.                 int minute;  
  29.                 if (StringUtils.isEmpty(arriveTimeBtn.getText().toString())) {  
  30.                     // Use the current time as the default values for the picker  
  31.                     final Calendar c = Calendar.getInstance();  
  32.                     hour = c.get(Calendar.HOUR_OF_DAY);  
  33.                     minute = c.get(Calendar.MINUTE);  
  34.                 } else {  
  35.                     hour = NewActActivity.arrive_hour;  
  36.                     minute = NewActActivity.arrive_min;  
  37.                 }  
  38.                 timePicker.setIs24HourView(true);  
  39.                 timePicker.setCurrentHour(hour);  
  40.                 timePicker.setCurrentMinute(minute);  
  41.                   
  42.                 // Build DateTimeDialog  
  43.                 AlertDialog.Builder builder = new AlertDialog.Builder(NewActActivity.this);  
  44.                 builder.setView(view);  
  45.                 builder.setTitle(R.string.new_act_date_time_picker_title);  
  46.                 builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {  
  47.                     @Override  
  48.                     public void onClick(DialogInterface dialog, int which) {  
  49.                         arrive_year = datePicker.getYear();  
  50.                         arrive_month = datePicker.getMonth();  
  51.                         arrive_day = datePicker.getDayOfMonth();  
  52.                         String dateStr = DateUtil.formatDate(arrive_year, arrive_month, arrive_day);  
  53.                         arriveDateBtn.setText(dateStr);  
  54.                           
  55.                         arrive_hour = timePicker.getCurrentHour();  
  56.                         arrive_min = timePicker.getCurrentMinute();  
  57.                         String timeStr = DateUtil.formatTime(arrive_hour, arrive_min);  
  58.                         arriveTimeBtn.setText(timeStr);  
  59.                     }  
  60.                 });  
  61.                 builder.show();  
  62.             }  
  63.         });  
这样就可以实现日期时间选择器了,这里就有点layout上的小问题,你是需要datepicker和timepicker水平排列还是竖直排列,竖直排列是没问题的:下面给出两个数值排列的效果图: 
(1)DatePicker控件中设置android:calendarViewShown="false" 时的效果图: 

Android之DatePicker和TimePicker实现以及自定义大小_第1张图片
(2)(1)DatePicker控件中设置android:spinnersShown="false" 时的效果图: 

Android之DatePicker和TimePicker实现以及自定义大小_第2张图片

当然,如果你android:calendarViewShown和android:spinnersShown都不设置为false的话,会同时显示日历和滚动条样式,我想一般不会有人想要这样的视图吧。 
水平排列是有问题的,那就是屏幕太挤,两个控件显示不全,看看效果图: 
Android之DatePicker和TimePicker实现以及自定义大小_第3张图片

可是有人就是有水平排列的需求怎么办?这就是本文要讲的第二个问题:改变datepicker和timepicker的宽度。 

网上找了很久,没有发现很有效的方法,说是这两个控件的子元素的宽度是不能自定义的,实际上把控件的所有属性看了一遍,也确实没有发现相关的属性;有人是通过自定义DatePicker和TimePicker来实现的,找了个demo,确实是实现了,不过已经相当于是自己写了一个插件了,我嫌麻烦,加之稳定性方面的考虑,没有去用,不过我会在最后把这个demo的src带上,有需要的人可以自己下载来研究。难道真不能改宽度吗?突然想到我是不是能从代码中的datePicker对象一步步往下找到其child,直接改child的宽度呢,于是debug,果然通过这种方式成功改变了宽度值,代码如下,只要在DemoActivity.java中增加一块专门用于实现改宽度的代码就行: 

DemoActivity.java: 
Java代码   收藏代码
  1. arriveAtBtn.setOnClickListener(new View.OnClickListener(){  
  2.             @SuppressLint("NewApi")  
  3.             @Override  
  4.             public void onClick(View v) {  
  5.                 View view = View.inflate(getApplicationContext(), R.layout.date_time_picker, null);  
  6.                 final DatePicker datePicker = (DatePicker)view.findViewById(R.id.new_act_date_picker);  
  7.                 final TimePicker timePicker = (TimePicker)view.findViewById(R.id.new_act_time_picker);  
  8.                   
  9.                 // Change DatePicker layout  
  10.                 LinearLayout dpContainer = (LinearLayout)datePicker.getChildAt(0)   ;   // LinearLayout  
  11.                 LinearLayout dpSpinner = (LinearLayout)dpContainer.getChildAt(0);       // 0 : LinearLayout; 1 : CalendarView  
  12.                 for(int i = 0; i < dpSpinner.getChildCount(); i ++) {  
  13.                     NumberPicker numPicker = (NumberPicker)dpSpinner.getChildAt(i);     // 0-2 : NumberPicker  
  14.                     LayoutParams params1 = new LayoutParams(120, LayoutParams.WRAP_CONTENT);  
  15.                     params1.leftMargin = 0;  
  16.                     params1.rightMargin = 30;  
  17.                     numPicker.setLayoutParams(params1);  
  18.                       
  19. //                  EditText cusET = (EditText)numPicker.getChildAt(0);     // CustomEditText  
  20. //                  cusET.setTextSize(14);  
  21. //                  cusET.setWidth(70);  
  22.                 }  
  23.                   
  24.                 // Change TimePicker layout  
  25.                 LinearLayout tpContainer = (LinearLayout)timePicker.getChildAt(0)   ;   // LinearLayout  
  26.                 LinearLayout tpSpinner = (LinearLayout)tpContainer.getChildAt(0);       // 0 : LinearLayout; 1 : CalendarView  
  27.                 for(int i = 0; i < tpSpinner.getChildCount(); i ++) {  
  28.                     // child(1) is a TextView ( : )  
  29.                     if (i == 1) {  
  30.                         continue;  
  31.                     }  
  32.                     NumberPicker numPicker = (NumberPicker)tpSpinner.getChildAt(i);     // 0 : NumberPicker; 1 : TextView; 2 : NumberPicker  
  33.                     LayoutParams params3 = new LayoutParams(100, LayoutParams.WRAP_CONTENT);  
  34.                     params3.leftMargin = 0;  
  35.                     params3.rightMargin = 30;  
  36.                     numPicker.setLayoutParams(params3);  
  37.                       
  38. //                  EditText cusET = (EditText)numPicker.getChildAt(0);     // CustomEditText  
  39. //                  cusET.setTextSize(14);  
  40. //                  cusET.setWidth(70);  
  41.                 }  
  42.                   
  43.                 // Init DatePicker  
  44.                 int year;  
  45.                 int month;  
  46.                 int day;  
  47.                 if (StringUtils.isEmpty(arriveDateBtn.getText().toString())) {  
  48.                     // Use the current date as the default date in the picker  
  49.                     final Calendar c = Calendar.getInstance();  
  50.                     year = c.get(Calendar.YEAR);  
  51.                     month = c.get(Calendar.MONTH);  
  52.                     day = c.get(Calendar.DAY_OF_MONTH);  
  53.                 } else {  
  54.                     year = NewActActivity.arrive_year;  
  55.                     month = NewActActivity.arrive_month;  
  56.                     day = NewActActivity.arrive_day;  
  57.                 }  
  58.                 datePicker.init(year, month, day, null);  
  59.                   
  60.                 // Init TimePicker  
  61.                 int hour;  
  62.                 int minute;  
  63.                 if (StringUtils.isEmpty(arriveTimeBtn.getText().toString())) {  
  64.                     // Use the current time as the default values for the picker  
  65.                     final Calendar c = Calendar.getInstance();  
  66.                     hour = c.get(Calendar.HOUR_OF_DAY);  
  67.                     minute = c.get(Calendar.MINUTE);  
  68.                 } else {  
  69.                     hour = NewActActivity.arrive_hour;  
  70.                     minute = NewActActivity.arrive_min;  
  71.                 }  
  72.                 timePicker.setIs24HourView(true);  
  73.                 timePicker.setCurrentHour(hour);  
  74.                 timePicker.setCurrentMinute(minute);  
  75.                   
  76.                 // Build DateTimeDialog  
  77.                 AlertDialog.Builder builder = new AlertDialog.Builder(NewActActivity.this);  
  78.                 builder.setView(view);  
  79.                 builder.setTitle(R.string.new_act_date_time_picker_title);  
  80.                 builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {  
  81.                     @Override  
  82.                     public void onClick(DialogInterface dialog, int which) {  
  83.                         arrive_year = datePicker.getYear();  
  84.                         arrive_month = datePicker.getMonth();  
  85.                         arrive_day = datePicker.getDayOfMonth();  
  86.                         String dateStr = DateUtil.formatDate(arrive_year, arrive_month, arrive_day);  
  87.                         arriveDateBtn.setText(dateStr);  
  88.                           
  89.                         arrive_hour = timePicker.getCurrentHour();  
  90.                         arrive_min = timePicker.getCurrentMinute();  
  91.                         String timeStr = DateUtil.formatTime(arrive_hour, arrive_min);  
  92.                         arriveTimeBtn.setText(timeStr);  
  93.                     }  
  94.                 });  
  95.                 builder.show();  
  96.             }  
  97.         });  
通过这种方式实现的效果图如下: 
Android之DatePicker和TimePicker实现以及自定义大小_第4张图片

其实这种方法也有问题:我的手机是1080P(5.5寸)的屏,显示效果是这样,如果屏幕小点,分辨率更低的屏呢,很可能屏幕宽度不够显示,当然你可以修改一下上面代码的逻辑,根据屏幕大小来动态设置控件的宽度值,而不是设成定值,具体的这些细节按自己的需求来做吧,我这里只是想记录一下自己发现的这种改变datepicker和timepicker宽度的方法,至于是否实用,我不负责,我只当是学习一下android。不过我的项目里最终没有用这个方案,最终选择了垂直排列的日历格式那个方案。 

http://android.blog.51cto.com/268543/333769

http://blog.csdn.net/wwj_748/article/details/38778631

http://i.ruby.blog.163.com/blog/static/24793417201296112559424/

你可能感兴趣的:(android,Datepicker,TimePicker)