<h1>基本用法</h1>
DatePickerDialog是一個封裝了DatePicker(日期選擇器)的Dialog對話框組件遭顶。DatePicker需要占據(jù)較大的布局空間,相比之下胸嘴,DatePickerDialog則以對話框的形式队萤,在我們需要設(shè)置日期時再顯示改控件。DatePickerDialog的使用也很方便:
一般我們使用構(gòu)造方法public DatePickerDialog(@NonNull Context context, @Nullable OnDateSetListener listener, int year, int month, int dayOfMonth)可以創(chuàng)建出一個DatePickerDialog對象击蹲。其中OnDateSetListener listener是用戶日期設(shè)置完成后的回調(diào)監(jiān)聽器署拟,該接口的void onDateSet(DatePicker view, int year, int month, int dayOfMonth);方法內(nèi)可以獲取到用戶設(shè)置的日期信息,在該方法內(nèi)我們可以對用戶輸入的日期信息做進一步的操作歌豺。
參數(shù)year推穷、month、dayOfMonth用來初始化DatePickerDialog默認(rèn)顯示的日期类咧。不過要注意參數(shù)month與Calendar類的month類似馒铃,都是從0開始表示,即1-12月依次對應(yīng)0-11痕惋。通常我們可以用Calendar.getInstance();獲取到一個表示當(dāng)前系統(tǒng)日期的Calendar對象区宇,用該對象來初始化DatePickerDialog,如下:
<pre>
Calendar c = null;
public void showDatePickerDialog(DatePickerDialog.OnDateSetListener listener) {
c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
int day = c.get(Calendar.DAY_OF_MONTH);
new CommonDatePickerDialog(DoctorCheckActivity.this, listener, year, month, day).show();
}
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DatePickerDialog.OnDateSetListener listener = new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
Log.i(year + "年" + ++month + "月" + dayOfMonth + "日");
}
};
showDatePickerDialog (listener);
}
});
</pre>
<h1>出現(xiàn)的問題</h1>
這段代碼執(zhí)行后值戳,觀察發(fā)現(xiàn)萧锉,如果點擊“完成”,Log會輸出兩次述寡,而如果通過點擊返回鍵或Dialog以外的部分來關(guān)閉改Dialog的話,則仍會輸出一次Log信息叶洞。在一般情況下鲫凶,我們希望只有當(dāng)用戶確定其輸入的日期信息后,才調(diào)用onDateSet()方法衩辟,但在這里無論是否確定輸入螟炫,都會回調(diào)onDateSet()方法,這顯然不是我們想要的艺晴。為什么會出現(xiàn)這樣的情況呢昼钻?
首先,我們知道當(dāng)Dialog被關(guān)閉時封寞,如按下“取消”然评、“確定”、返回鍵或Dialog以外的部分狈究,都會調(diào)用dismiss()方法碗淌,進一步調(diào)用onStop()方法。而從Android 4.1到Android4.4(API 16-19)抖锥,DatePickerDialog的源碼都重寫了onStop()方法:
<pre>
@Override
protected void onStop() {
tryNotifyDateSet();
super.onStop();
}
private void tryNotifyDateSet() {
if (mCallBack != null) {
mDatePicker.clearFocus();
mCallBack.onDateSet(mDatePicker, mDatePicker.getYear(),
mDatePicker.getMonth(), mDatePicker.getDayOfMonth());
}
}
</pre>
由源碼可知亿眠,這些版本的DatePickerDialog在關(guān)閉時會再次調(diào)用DatePickerDialog. OnDateSetListener監(jiān)聽器的onDateSet()方法。
<h1>解決方法</h1>
由以上分析可知磅废,問題出現(xiàn)的原因在于在某些版本的系統(tǒng)中纳像,DatePickerDialog的生命周期onStop()方法會調(diào)用onDateSet()方法。因此拯勉,我們可以自定義CommonDatePickerDialog繼承自O(shè)nDateSetListener竟趾,重寫onStop()方法:
<pre>
class CommonDatePickerDialog extends DatePickerDialog {
public CommonDatePickerDialog(@NonNull Context context, @Nullable OnDateSetListener listener, int year, int month, int dayOfMonth) {
super(context, listener, year, month, dayOfMonth);
}
@Override
protected void onStop() {
//super.onStop();
}
}
</pre>
使CommonDatePickerDialog的onStop()方法成為空實現(xiàn)憔购,不要執(zhí)行父類的onStop()方法。
當(dāng)然潭兽,DatePickerDialog的父類是Dialog倦始,我們也可以自定義Dialog的按鈕及其監(jiān)聽回調(diào),即不使用OnDateSetListener來監(jiān)聽“確認(rèn)”按鈕:
<pre>
public void pickDate(View view) {
Calendar cal = Calendar.getInstance();
final DatePickerDialog mDialog = new DatePickerDialog(this, null, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH));
//手動設(shè)置按鈕
mDialog.setButton(DialogInterface.BUTTON_POSITIVE, "完成", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//通過mDialog.getDatePicker()獲得dialog上的DatePicker組件山卦,然后可以獲取日期信息
DatePicker datePicker = mDialog.getDatePicker();
int year = datePicker.getYear();
int month = datePicker.getMonth();
int day = datePicker.getDayOfMonth();
System.out.println(year + "," + month + "," + day);
}
});
//取消按鈕鞋邑,如果不需要直接不設(shè)置即可
mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
System.out.println("BUTTON_NEGATIVE~~");
}
});
Dialog.show();
}
</pre>
<h1>參考</h1>
http://bbs.9ria.com/forum.php?mod=viewthread&tid=205312
http://www.devba.com/index.php/archives/6187.html