1. 程式人生 > >Android之DatePicker和TimePicker實現以及自定義大小

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.     <!-- <DatePicker  
  8.         android:id="@+id/new_act_date_picker"  
  9.         android:layout_width="0dip"  
  10.         android:layout_height="wrap_content"  
  11.         android:layout_weight="0.6"  
  12.         android:calendarViewShown="false" />  
  13.     <TimePicker   
  14.         android:id="@+id/new_act_time_picker"  
  15.         android:layout_width="0dip"  
  16.         android:layout_height="wrap_content"  
  17.         android:layout_weight="0.3"/> -->  
  18.     <DatePicker  
  19.         android:id="@+id/new_act_date_picker"  
  20.         android:layout_width="wrap_content"  
  21.         android:layout_height="wrap_content"  
  22.         android:calendarViewShown="false" />  
  23.     <TimePicker   
  24.         android:id="@+id/new_act_time_picker"  
  25.         android:layout_width="wrap_content"  
  26.         android:layout_height="wrap_content"/>  
  27. </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.                 // Init DatePicker  
  9.                 int year;  
  10.                 int month;  
  11.                 int day;  
  12.                 if (StringUtils.isEmpty(arriveDateBtn.getText().toString())) {  
  13.                     // Use the current date as the default date in the picker  
  14.                     final Calendar c = Calendar.getInstance();  
  15.                     year = c.get(Calendar.YEAR);  
  16.                     month = c.get(Calendar.MONTH);  
  17.                     day = c.get(Calendar.DAY_OF_MONTH);  
  18.                 } else {  
  19.                     year = NewActActivity.arrive_year;  
  20.                     month = NewActActivity.arrive_month;  
  21.                     day = NewActActivity.arrive_day;  
  22.                 }  
  23.                 datePicker.init(year, month, day, null);  
  24.                 // Init TimePicker  
  25.                 int hour;  
  26.                 int minute;  
  27.                 if (StringUtils.isEmpty(arriveTimeBtn.getText().toString())) {  
  28.                     // Use the current time as the default values for the picker  
  29.                     final Calendar c = Calendar.getInstance();  
  30.                     hour = c.get(Calendar.HOUR_OF_DAY);  
  31.                     minute = c.get(Calendar.MINUTE);  
  32.                 } else {  
  33.                     hour = NewActActivity.arrive_hour;  
  34.                     minute = NewActActivity.arrive_min;  
  35.                 }  
  36.                 timePicker.setIs24HourView(true);  
  37.                 timePicker.setCurrentHour(hour);  
  38.                 timePicker.setCurrentMinute(minute);  
  39.                 // Build DateTimeDialog  
  40.                 AlertDialog.Builder builder = new AlertDialog.Builder(NewActActivity.this);  
  41.                 builder.setView(view);  
  42.                 builder.setTitle(R.string.new_act_date_time_picker_title);  
  43.                 builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {  
  44.                     @Override  
  45.                     public void onClick(DialogInterface dialog, int which) {  
  46.                         arrive_year = datePicker.getYear();  
  47.                         arrive_month = datePicker.getMonth();  
  48.                         arrive_day = datePicker.getDayOfMonth();  
  49.                         String dateStr = DateUtil.formatDate(arrive_year, arrive_month, arrive_day);  
  50.                         arriveDateBtn.setText(dateStr);  
  51.                         arrive_hour = timePicker.getCurrentHour();  
  52.                         arrive_min = timePicker.getCurrentMinute();  
  53.                         String timeStr = DateUtil.formatTime(arrive_hour, arrive_min);  
  54.                         arriveTimeBtn.setText(timeStr);  
  55.                     }  
  56.                 });  
  57.                 builder.show();  
  58.             }  
  59.         });  
這樣就可以實現日期時間選擇器了,這裡就有點layout上的小問題,你是需要datepicker和timepicker水平排列還是豎直排列,豎直排列是沒問題的:下面給出兩個數值排列的效果圖: 
(1)DatePicker控制元件中設定android:calendarViewShown="false" 時的效果圖: 


(2)(1)DatePicker控制元件中設定android:spinnersShown="false" 時的效果圖: 



當然,如果你android:calendarViewShown和android:spinnersShown都不設定為false的話,會同時顯示日曆和滾動條樣式,我想一般不會有人想要這樣的檢視吧。 
水平排列是有問題的,那就是螢幕太擠,兩個控制元件顯示不全,看看效果圖: 


可是有人就是有水平排列的需求怎麼辦?這就是本文要講的第二個問題:改變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.                 // Change DatePicker layout  
  9.                 LinearLayout dpContainer = (LinearLayout)datePicker.getChildAt(0)   ;   // LinearLayout  
  10.                 LinearLayout dpSpinner = (LinearLayout)dpContainer.getChildAt(0);       // 0 : LinearLayout; 1 : CalendarView  
  11.                 for(int i = 0; i < dpSpinner.getChildCount(); i ++) {  
  12.                     NumberPicker numPicker = (NumberPicker)dpSpinner.getChildAt(i);     // 0-2 : NumberPicker  
  13.                     LayoutParams params1 = new LayoutParams(120, LayoutParams.WRAP_CONTENT);  
  14.                     params1.leftMargin = 0;  
  15.                     params1.rightMargin = 30;  
  16.                     numPicker.setLayoutParams(params1);  
  17. //                  EditText cusET = (EditText)numPicker.getChildAt(0);     // CustomEditText  
  18. //                  cusET.setTextSize(14);  
  19. //                  cusET.setWidth(70);  
  20.                 }  
  21.                 // Change TimePicker layout  
  22.                 LinearLayout tpContainer = (LinearLayout)timePicker.getChildAt(0)   ;   // LinearLayout  
  23.                 LinearLayout tpSpinner = (LinearLayout)tpContainer.getChildAt(0);       // 0 : LinearLayout; 1 : CalendarView  
  24.                 for(int i = 0; i < tpSpinner.getChildCount(); i ++) {  
  25.                     // child(1) is a TextView ( : )  
  26.                     if (i == 1) {  
  27.                         continue;  
  28.                     }  
  29.                     NumberPicker numPicker = (NumberPicker)tpSpinner.getChildAt(i);     // 0 : NumberPicker; 1 : TextView; 2 : NumberPicker  
  30.                     LayoutParams params3 = new LayoutParams(100, LayoutParams.WRAP_CONTENT);  
  31.                     params3.leftMargin = 0;  
  32.                     params3.rightMargin = 30;  
  33.                     numPicker.setLayoutParams(params3);  
  34. //                  EditText cusET = (EditText)numPicker.getChildAt(0);     // CustomEditText  
  35. //                  cusET.setTextSize(14);  
  36. //                  cusET.setWidth(70);  
  37.                 }  
  38.                 // Init DatePicker  
  39.                 int year;  
  40.                 int month;  
  41.                 int day;  
  42.                 if (StringUtils.isEmpty(arriveDateBtn.getText().toString())) {  
  43.                     // Use the current date as the default date in the picker  
  44.                     final Calendar c = Calendar.getInstance();  
  45.                     year = c.get(Calendar.YEAR);  
  46.                     month = c.get(Calendar.MONTH);  
  47.                     day = c.get(Calendar.DAY_OF_MONTH);  
  48.                 } else {  
  49.                     year = NewActActivity.arrive_year;  
  50.                     month = NewActActivity.arrive_month;  
  51.                     day = NewActActivity.arrive_day;  
  52.                 }  
  53.                 datePicker.init(year, month, day, null);  
  54.                 // Init TimePicker  
  55.                 int hour;  
  56.                 int minute;  
  57.                 if (StringUtils.isEmpty(arriveTimeBtn.getText().toString())) {  
  58.