Android日期時間選擇器實現以及自定義大小


本文主要講兩個內容: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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM