終于來(lái)到第12章啦云茸!對(duì)話框在各類(lèi)應(yīng)用中見(jiàn)到的幾率還是蠻多的蜓堕,這可就實(shí)用了,漂亮點(diǎn)的對(duì)話框還是提升用戶體驗(yàn)?zāi)貇
創(chuàng)建 DialogFragment
曾經(jīng)的我寫(xiě)代碼闷畸,創(chuàng)建對(duì)話框,都是直接顯示AlertDialog視圖的吞滞,然而現(xiàn)在看到本書(shū)推薦是將AlertDialog封裝在DialogFragment(Fragment的子類(lèi))實(shí)例中使用佑菩,用FragmentManager管理,更為靈活冯吓。而且倘待,在旋轉(zhuǎn)設(shè)備時(shí)用AlertDialog的話會(huì)消失,而封裝在fragment中的AlertDialog則不會(huì)有此問(wèn)題(旋轉(zhuǎn)后组贺,對(duì)話框會(huì)被重建恢復(fù))凸舵。看來(lái)失尖,今后寫(xiě)代碼還是注意了啊奄,得轉(zhuǎn)變轉(zhuǎn)變了渐苏,多看書(shū),還是漲姿勢(shì)的菇夸。
- 創(chuàng)建DatePickerFragment的DialogFragment子類(lèi)琼富。
- 在DatePickerFragment中,創(chuàng)建并配置顯示DatePicker組件的AlertDialog實(shí)例庄新。(DatePickerFragment同樣由CrimePagerActivity托管)
- 借助FragmentManager在屏幕上顯示對(duì)話框鞠眉。
接下來(lái),實(shí)踐代碼啦择诈,注意引入支持庫(kù)中的包械蹋。
新一點(diǎn)的系統(tǒng)看到的日歷選擇器還是挺好看的喔~
使用布局文件實(shí)例化視圖對(duì)象能更加方便的拓展噢,推薦用布局文件羞芍。雖然哗戈,
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
DatePicker datePicker = new DatePicker(getActivity());
return new AlertDialog.Builder(getActivity())
.setView(datePicker)
...
.create();
}
這樣也能創(chuàng)建DatePicker對(duì)象。
設(shè)備配置改變時(shí)荷科,具有ID屬性的視圖可以保存運(yùn)行狀態(tài)唯咬;而以dialog_date.xml布局創(chuàng)建DatePicker時(shí),編譯工具已為DatePicker生成了唯一的ID畏浆。所以胆胰,設(shè)備旋轉(zhuǎn),用戶所選日期也都會(huì)得到保留全度。
fragment 間的數(shù)據(jù)傳遞
現(xiàn)在同一個(gè)activity托管的兩個(gè)fragment之間要進(jìn)行數(shù)據(jù)傳遞了煮剧,來(lái)吧,本小結(jié)開(kāi)始了将鸵。
- 在DatePickerFragment中新建一個(gè)newInstance(Date)方法,然后將Date作為argument附加給fragment佑颇,這樣就將crime的日期傳遞給DatePickerFragment了顶掉。
這里由于DatePicker對(duì)象初始化涉及到整數(shù)形式的年、月挑胸、日痒筒,所以使用到了Calendar對(duì)象,用Date配置它茬贵,從而得到年月日簿透。有關(guān)Calendar、Date知識(shí)點(diǎn)解藻,實(shí)踐總結(jié)篇 :http://www.reibang.com/p/57cd6ead77c0
- 將CrimeFragment設(shè)置成DatePickerFragment的目標(biāo)fragment老充;傳遞數(shù)據(jù)給目標(biāo)fragment;在目標(biāo)fragment的 onActivityResult()接收數(shù)據(jù)螟左。
fragment中的public void setTargetFragment(Fragment fragment, int requestCode) 方法可以建立兩個(gè)fragment的關(guān)聯(lián)啡浊。
dialog.setTargetFragment(CrimeFragment.this, REQUEST_DATE);
DatePrickerFragment中添加下述方法觅够,為了返回傳遞數(shù)據(jù):
private void sendResult(int resultCode, Date date) {
if (getTargetFragment() == null) {
return;
}
Intent intent = new Intent();
intent.putExtra(EXTRA_DATE, date);
getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent);
}
接收數(shù)據(jù)核心代碼:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK){
return;
}
if (requestCode == REQUEST_DATE){
Date date = (Date) data.getSerializableExtra(DatePickerFragment.EXTRA_DATE);
mCrime.setDate(date);
updateDate(btnDate, mCrime);
}
}
可以覆蓋DialogFragment.
onCreateView(...)方法,以便顯示全屏fragment巷嚣,根據(jù)不同的需求喘先,可實(shí)現(xiàn)不同設(shè)備上的信息呈現(xiàn)。
挑戰(zhàn)練習(xí):更多對(duì)話框
(另寫(xiě)一個(gè)名為T(mén)imePickerFragment的對(duì)話框fragment廷粒,允許用戶使用TimePicker組件選擇crime發(fā)生的具體時(shí)間窘拯。在CrimeFragment用戶界面上再添加一個(gè)按鈕,以顯示TimePickerFragment視圖界面坝茎。)
我的解決方案吧树枫,創(chuàng)建TimePickerFragment這里的寫(xiě)法跟上述一樣的啦,然后CrimeFragment添加了個(gè)按鈕選時(shí)間景东,更新還是在date的那個(gè)按鈕上砂轻。上代碼啦:
public class TimePickerFragment extends DialogFragment {
private static final String ARG_TIME = "time";
public static final String EXTRA_TIME =
"com.bignerdranch.android.criminalintent.time";
private TimePicker mTimePicker;
private Calendar mCalendar;
public static TimePickerFragment newInstance(Date date) {
Bundle bundle = new Bundle();
bundle.putSerializable(ARG_TIME, date);
TimePickerFragment timePickerFragment = new TimePickerFragment();
timePickerFragment.setArguments(bundle);
return timePickerFragment;
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Date date = (Date) getArguments().getSerializable(ARG_TIME);
mCalendar = Calendar.getInstance();
mCalendar.setTime(date);
int hour = mCalendar.get(Calendar.HOUR_OF_DAY);
int minute = mCalendar.get(Calendar.MINUTE);
View view = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_time, null);
mTimePicker = view.findViewById(R.id.dialog_time_picker);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mTimePicker.setHour(hour);
mTimePicker.setMinute(minute);
} else {
mTimePicker.setCurrentHour(hour);
mTimePicker.setCurrentMinute(minute);
}
return new AlertDialog.Builder(getActivity())
.setView(view)
.setTitle(R.string.time_picker_title)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int hour, minute;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
hour = mTimePicker.getHour();
minute = mTimePicker.getMinute();
} else {
hour = mTimePicker.getCurrentHour();
minute = mTimePicker.getCurrentMinute();
}
mCalendar.set(Calendar.HOUR_OF_DAY, hour);
mCalendar.set(Calendar.MINUTE, minute);
sendResult(Activity.RESULT_OK, mCalendar.getTime());
}
})
.show();
}
private void sendResult(int resultCode, Date date) {
if (getTargetFragment() == null) {
return;
}
Intent intent = new Intent();
intent.putExtra(EXTRA_TIME, date);
getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent);
}
}
CrimeFragment.java中的核心代碼:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK){
return;
}
if (requestCode == REQUEST_DATE){
Date date = (Date) data.getSerializableExtra(DatePickerFragment.EXTRA_DATE);
mCrime.setDate(date);
updateDate(btnDate, mCrime);
}else if (requestCode == REQUEST_TIME){
Date date = (Date) data.getSerializableExtra(TimePickerFragment.EXTRA_TIME);
mCrime.setDate(date);
updateDate(btnDate, mCrime);
}
}
應(yīng)該還是很容易看懂的,emmm... 我是這么想嘍~~~
挑戰(zhàn)練習(xí):實(shí)現(xiàn)響應(yīng)式 DialogFragment
這個(gè)挑戰(zhàn)練習(xí)貌似有點(diǎn)復(fù)雜斤吐,最后都叫我提前學(xué)習(xí)17章內(nèi)容再來(lái)完成了搔涝,所以...哈哈~ 先這樣吧,先不做了和措。