问题:首先看一个简单的练习。另写一个名为 TimePickerFragment 的对话框fragment,允许用户使用 TimePicker 组件选择crime发生的具体时间。在 CrimeFragment 用户界面上再添加一个按钮,以显示 TimePickerFragment 视图界面。
1:首先创建dialog_time.xml视图,内容为
<DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/dialog_date_picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:calendarViewShown="false">
</DatePicker>
2:在fragment_crime.xml中添加按钮
<Button
android:id="@+id/crime_time"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
3:直接复制一份DatePickerFragment.class来修改,大多都是差不多的
4:首先思考一下,Date对象是包含日期和时间的,所以修改的时候只修改时间就可以了
按照流程,打开CrimeFragment页面时,按钮上必须显示时间,新增一个updateTime方法,
直接在CrimeFragment#onCreateView方法中调用
private void updateTime() {
mTimeButton.setText(DateFormat.format("h:mm a", mCrime.getDate()));
}
用来顺便指定时间显示的格式
5:点击按钮后弹出TimePicker对话框,需要显示刚刚按钮上显示的时间
TimePickerFragment#onCreateDialog
Date date = (Date) getArguments().getSerializable(ARG_DATE); //获取从前一个fragment传进来的date
final Calendar calendar = Calendar.getInstance(); //获得日历
calendar.setTime(date); 更正日历的时间为Crime对象的时间
final int year = calendar.get(Calendar.YEAR); //获取Crime对象的日期的年月日时分
final int month = calendar.get(Calendar.MONTH);
final int day = calendar.get(Calendar.DAY_OF_MONTH);
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mTimePicker.setHour(hour); //设置时间选择器对话框的
mTimePicker.setMinute(minute);
} else {
mTimePicker.setCurrentHour(hour);
mTimePicker.setCurrentMinute(minute);
}
CrimeFragment#onCreateView
private Button mTimeButton; //定义全局按钮
mTimeButton = v.findViewById(R.id.crime_time); //实例化视图按钮
mTimeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FragmentManager manager = getFragmentManager();
TimePickerFragment dialog = TimePickerFragment.newInstance(mCrime.getDate());
dialog.setTargetFragment(CrimeFragment.this, REQUEST_TIME); //设置目标Fragment,也就是前一个Fragment
dialog.show(manager, DIALOG_TIME); //第一个参数是FragmentManager,它会自动管理弹出的日历对话框,第二个是TAG
}
});
6:当选好时间后点击确定,从TimePicker中获取时间,写入到mCrime中,这里麻烦的地方是需要在两个Fragment中传递数据
从TimePicker中获取时间:TimePickerFragment#onCreateDialog
return new AlertDialog.Builder(getActivity())
.setView(view)
.setTitle(R.string.time_picker_title)
.setNegativeButton(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(); //从TimePicker中获取时间
minute = mTimePicker.getMinute();
} else {
hour = mTimePicker.getCurrentHour();
minute = mTimePicker.getCurrentMinute();
}
Date date = new GregorianCalendar(year, month, day, hour, minute).getTime(); //创建一个阳历
sendResult(Activity.RESULT_OK, date); //这个方法会自动回调CrimeFragment#onActivityResult方法
}
})
.create();
private void sendResult(int resultCode, Date date) { //这个方法会自动回调CrimeFragment#onActivityResult方法
if (getTargetFragment() == null) {
return;
}
Intent intent = new Intent(); //传递数据
intent.putExtra(EXTRA_DATE, date); //这个EXTRA_DATE一直都是使用的DatePickerFragment中的常亮,毕竟两个按钮共用一个Date
//调用目标Fragment的onActivityResult,给他返回数据
getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent);
}
7:回调CrimeFragment中的onActivityResult方法,处理按钮上显示的日期
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK) {
return;
}
Date date = (Date) data.getSerializableExtra(DatePickerFragment.EXTRA_DATE); //获取刚刚intent中的日期
mCrime.setDate(date); //同时设置到Crime对象的date属性中
if (requestCode == REQUEST_DATE) {
updateDate();
}
if (requestCode == REQUEST_TIME) { //根据请求类型处理不同的结果
updateTime(); //更新第二个按钮的显示
updateDate(); //更新第一个按钮的显示,要不然第一个按钮要等到重新打开这个页面才会更新
}
}
8:第5步CrimeFragment#onCreateView方法里有个
TimePickerFragment.newInstance(mCrime.getDate());
如果是复制的要把DatePickerFragment改成TimePickerFragment。
public static TimePickerFragment newInstance(Date date) {
Bundle bundle = new Bundle();
bundle.putSerializable(ARG_DATE, date);
TimePickerFragment fragment = new TimePickerFragment();
fragment.setArguments(bundle);
return fragment;
}
DatePickerFragment#EXTRA_DATE常量必须改成public,要不然TimePickerFragment无法访问。