本文主要講兩個內容:1.如何將DatePicker和TimePicker放在一個dialog里面;2.改變他們的寬度;
問題1:其實現思路就是自定義一個Dialog,然后往里面同時放入DatePicker和TimePicker,直接貼代碼:
date_time_picker.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal" > <!-- <DatePicker android:id="@+id/new_act_date_picker" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="0.6" android:calendarViewShown="false" /> <TimePicker android:id="@+id/new_act_time_picker" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="0.3"/> --> <DatePicker android:id="@+id/new_act_date_picker" android:layout_width="wrap_content" android:layout_height="wrap_content" android:calendarViewShown="false" /> <TimePicker android:id="@+id/new_act_time_picker" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>
然后在需要顯示日期時間選擇器的地方(一般是一個onClickListener中)實例化dialog:
DemoActivity.java
arriveAtBtn.setOnClickListener(new View.OnClickListener(){ @SuppressLint("NewApi") @Override public void onClick(View v) { View view = View.inflate(getApplicationContext(), R.layout.date_time_picker, null); final DatePicker datePicker = (DatePicker)view.findViewById(R.id.new_act_date_picker); final TimePicker timePicker = (TimePicker)view.findViewById(R.id.new_act_time_picker); // Init DatePicker int year; int month; int day; if (StringUtils.isEmpty(arriveDateBtn.getText().toString())) { // Use the current date as the default date in the picker final Calendar c = Calendar.getInstance(); year = c.get(Calendar.YEAR); month = c.get(Calendar.MONTH); day = c.get(Calendar.DAY_OF_MONTH); } else { year = NewActActivity.arrive_year; month = NewActActivity.arrive_month; day = NewActActivity.arrive_day; } datePicker.init(year, month, day, null); // Init TimePicker int hour; int minute; if (StringUtils.isEmpty(arriveTimeBtn.getText().toString())) { // Use the current time as the default values for the picker final Calendar c = Calendar.getInstance(); hour = c.get(Calendar.HOUR_OF_DAY); minute = c.get(Calendar.MINUTE); } else { hour = NewActActivity.arrive_hour; minute = NewActActivity.arrive_min; } timePicker.setIs24HourView(true); timePicker.setCurrentHour(hour); timePicker.setCurrentMinute(minute); // Build DateTimeDialog AlertDialog.Builder builder = new AlertDialog.Builder(NewActActivity.this); builder.setView(view); builder.setTitle(R.string.new_act_date_time_picker_title); builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { arrive_year = datePicker.getYear(); arrive_month = datePicker.getMonth(); arrive_day = datePicker.getDayOfMonth(); String dateStr = DateUtil.formatDate(arrive_year, arrive_month, arrive_day); arriveDateBtn.setText(dateStr); arrive_hour = timePicker.getCurrentHour(); arrive_min = timePicker.getCurrentMinute(); String timeStr = DateUtil.formatTime(arrive_hour, arrive_min); arriveTimeBtn.setText(timeStr); } }); builder.show(); } });
這樣就可以實現日期時間選擇器了,這里就有點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:
arriveAtBtn.setOnClickListener(new View.OnClickListener(){ @SuppressLint("NewApi") @Override public void onClick(View v) { View view = View.inflate(getApplicationContext(), R.layout.date_time_picker, null); final DatePicker datePicker = (DatePicker)view.findViewById(R.id.new_act_date_picker); final TimePicker timePicker = (TimePicker)view.findViewById(R.id.new_act_time_picker); // Change DatePicker layout LinearLayout dpContainer = (LinearLayout)datePicker.getChildAt(0) ; // LinearLayout LinearLayout dpSpinner = (LinearLayout)dpContainer.getChildAt(0); // 0 : LinearLayout; 1 : CalendarView for(int i = 0; i < dpSpinner.getChildCount(); i ++) { NumberPicker numPicker = (NumberPicker)dpSpinner.getChildAt(i); // 0-2 : NumberPicker LayoutParams params1 = new LayoutParams(120, LayoutParams.WRAP_CONTENT); params1.leftMargin = 0; params1.rightMargin = 30; numPicker.setLayoutParams(params1); // EditText cusET = (EditText)numPicker.getChildAt(0); // CustomEditText // cusET.setTextSize(14); // cusET.setWidth(70); } // Change TimePicker layout LinearLayout tpContainer = (LinearLayout)timePicker.getChildAt(0) ; // LinearLayout LinearLayout tpSpinner = (LinearLayout)tpContainer.getChildAt(0); // 0 : LinearLayout; 1 : CalendarView for(int i = 0; i < tpSpinner.getChildCount(); i ++) { // child(1) is a TextView ( : ) if (i == 1) { continue; } NumberPicker numPicker = (NumberPicker)tpSpinner.getChildAt(i); // 0 : NumberPicker; 1 : TextView; 2 : NumberPicker LayoutParams params3 = new LayoutParams(100, LayoutParams.WRAP_CONTENT); params3.leftMargin = 0; params3.rightMargin = 30; numPicker.setLayoutParams(params3); // EditText cusET = (EditText)numPicker.getChildAt(0); // CustomEditText // cusET.setTextSize(14); // cusET.setWidth(70); } // Init DatePicker int year; int month; int day; if (StringUtils.isEmpty(arriveDateBtn.getText().toString())) { // Use the current date as the default date in the picker final Calendar c = Calendar.getInstance(); year = c.get(Calendar.YEAR); month = c.get(Calendar.MONTH); day = c.get(Calendar.DAY_OF_MONTH); } else { year = NewActActivity.arrive_year; month = NewActActivity.arrive_month; day = NewActActivity.arrive_day; } datePicker.init(year, month, day, null); // Init TimePicker int hour; int minute; if (StringUtils.isEmpty(arriveTimeBtn.getText().toString())) { // Use the current time as the default values for the picker final Calendar c = Calendar.getInstance(); hour = c.get(Calendar.HOUR_OF_DAY); minute = c.get(Calendar.MINUTE); } else { hour = NewActActivity.arrive_hour; minute = NewActActivity.arrive_min; } timePicker.setIs24HourView(true); timePicker.setCurrentHour(hour); timePicker.setCurrentMinute(minute); // Build DateTimeDialog AlertDialog.Builder builder = new AlertDialog.Builder(NewActActivity.this); builder.setView(view); builder.setTitle(R.string.new_act_date_time_picker_title); builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { arrive_year = datePicker.getYear(); arrive_month = datePicker.getMonth(); arrive_day = datePicker.getDayOfMonth(); String dateStr = DateUtil.formatDate(arrive_year, arrive_month, arrive_day); arriveDateBtn.setText(dateStr); arrive_hour = timePicker.getCurrentHour(); arrive_min = timePicker.getCurrentMinute(); String timeStr = DateUtil.formatTime(arrive_hour, arrive_min); arriveTimeBtn.setText(timeStr); } }); builder.show(); } });
通過這種方式實現的效果圖如下:
其實這種方法也有問題:我的手機是1080P(5.5寸)的屏,顯示效果是這樣,如果屏幕小點,分辨率更低的屏呢,很可能屏幕寬度不夠顯示,當然你可以修改一下上面代碼的邏輯,根據屏幕大小來動態設置控件的寬度值,而不是設成定值,具體的這些細節按自己的需求來做吧,我這里只是想記錄一下自己發現的這種改變datepicker和timepicker寬度的方法,至於是否實用,我不負責,我只當是學習一下android。不過我的項目里最終沒有用這個方案,最終選擇了垂直排列的日歷格式那個方案。
最后附上別人實現的自定義DatePicker和TimePicker(MyPicker)
MyPicker.rar (120 KB)