挑战练习12.3 更多对话框
首先看一个简单的练习。另写一个名为TimePickerFragment的对话框fragment,允许用户使用TimePicker组件选择crime发生的具体时间。在CrimeFragment用户界面上再添加一个按钮,以显示TimePickerFragment视图界面。
跟书里DatePicker的步骤很相似,大部分代码相同,可以直接复制之前的改改就行,Date对象是包含日期和时间的,所以修改的时候只修改时间就可以了
1.首先创建布局文件dialog_time.xml
1 <TimePicker xmlns:android="http://schemas.android.com/apk/res/android" 2 android:id="@+id/dialog_time_picker" 3 android:layout_width="wrap_content" 4 android:layout_height="wrap_content" 5 android:calendarViewShown="false" 6 android:timePickerMode="spinner"> 7 </TimePicker>
2.在fragment_crime.xml中原本的date按钮后面添加一个按钮,代码跟date差不多,id换成crime_time
1 <Button 2 android:id="@+id/crime_time" 3 android:layout_width="match_parent" 4 android:layout_height="wrap_content" />
3.添加一个新的class名为TimePickerFragment
1 package com.bignerdranch.android.criminalintent.fragment; 2 3 import android.app.Activity; 4 import android.app.Dialog; 5 import android.content.DialogInterface; 6 import android.content.Intent; 7 import android.os.Build; 8 import android.os.Bundle; 9 import android.support.v4.app.DialogFragment; 10 import android.support.v7.app.AlertDialog; 11 import android.view.LayoutInflater; 12 import android.view.View; 13 import android.widget.TimePicker; 14 15 16 import com.bignerdranch.android.criminalintent.R; 17 18 import java.util.Calendar; 19 import java.util.Date; 20 import java.util.GregorianCalendar; 21 22 public class TimePickerFragment extends DialogFragment { 23 //两个按钮共用一个EXTRA_DATE,所以不用新添加一个TimePicker专用的EXTRA_TIME 24 public static final String EXTRA_DATE = "com.bignerdranch.android.criminalintent.date"; 25 26 private static final String ARG_DATE = "date"; 27 28 private TimePicker mTimePicker; 29 30 @Override 31 public Dialog onCreateDialog(Bundle savedInstanceState) { 32 Date date = (Date) getArguments().getSerializable(ARG_DATE); 33 final Calendar calendar = Calendar.getInstance(); 34 calendar.setTime(date); 35 //一定得加final修饰年月日,不然GregorianCalendar的构造方法会报错 36 final int year = calendar.get(Calendar.YEAR); 37 final int month = calendar.get(Calendar.MONTH); 38 final int day = calendar.get(Calendar.DAY_OF_MONTH); 39 //时分 40 int hour = calendar.get(Calendar.HOUR_OF_DAY); 41 int minute = calendar.get(Calendar.MINUTE); 42 43 View v = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_time, null); 44 45 mTimePicker = (TimePicker) v.findViewById(R.id.dialog_time_picker); 46 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 47 mTimePicker.setHour(hour); 48 mTimePicker.setMinute(minute); 49 } else { 50 mTimePicker.setCurrentHour(hour); 51 mTimePicker.setCurrentMinute(minute); 52 } 53 54 return new AlertDialog.Builder(getActivity()) 55 .setView(v) 56 .setTitle(R.string.date_picker_title) 57 .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 58 @Override 59 public void onClick(DialogInterface dialog, int which) { 60 int hour, minute; 61 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 62 hour = mTimePicker.getHour(); 63 minute = mTimePicker.getMinute(); 64 } else { 65 hour = mTimePicker.getCurrentHour(); 66 minute = mTimePicker.getCurrentMinute(); 67 } 68 Date date = new GregorianCalendar(year, month, day, hour, minute).getTime(); 69 sendResult(Activity.RESULT_OK, date); 70 } 71 }) 72 .create(); 73 } 74 75 private void sendResult(int resultCode, Date date) { 76 if (getTargetFragment() == null) { 77 return; 78 } 79 Intent intent = new Intent(); 80 intent.putExtra(EXTRA_DATE, date); 81 getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent); 82 } 83 84 public static TimePickerFragment newInstance(Date date) { 85 Bundle args = new Bundle(); 86 args.putSerializable(ARG_DATE, date); 87 TimePickerFragment fragment = new TimePickerFragment(); 88 fragment.setArguments(args); 89 return fragment; 90 } 91 }
可以看到大部分代码跟DatePickerFragment比较类似的,类似的代码只不过把DatePicker换成了TimePicker而已,关于键值对不用修改,是因为两个按钮共用一个date,所以不用专门添加新的。不同点就是添加了时跟分的变量还有赋值处可以看到多了具体时间的赋值。
4.在CrimeFragment里面添加全局变量Time按钮、字符串变量DIALOG_TIME以及REQUEST_TIME判断点击的是哪个按钮
1 private Button mTimeButton; 2 private static final String DIALOG_TIME = "DialogTime"; 3 private static final int REQUEST_TIME = 0;
5.在CrimeFragment添加一个新的updateTime方法更新时间并在onCreateView里面调用,顺便控件绑定mTimeButton按钮
1 private void updateTime() 2 { 3 mTimeButton.setText(DateFormat.format("h:mm a", mCrime.getmDate())); 4 }
1 mTimeButton = (Button)v.findViewById(R.id.crime_time); 2 updateTime(); 3 mTimeButton.setOnClickListener(new View.OnClickListener() { 4 @Override 5 public void onClick(View v) { 6 FragmentManager manager = getFragmentManager(); 7 TimePickerFragment dialog = TimePickerFragment.newInstance(mCrime.getmDate()); 8 dialog.setTargetFragment(CrimeFragment.this, REQUEST_TIME);//设置目标Fragment,也就是前一个Fragment 9 dialog.show(manager,DIALOG_TIME);//第一个参数是FragmentManager,自动管理弹出的日历对话框,第二个是TAG 10 } 11 });
6.修改CrimeFragment中的onActivityResult方法,因为在TimePickerFragment中回调了,要处理传回来的结果
1 @Override 2 public void onActivityResult(int requestCode, int resultCode, Intent data) { 3 if (resultCode != Activity.RESULT_OK) { 4 return; 5 } 6 Date date = (Date) data.getSerializableExtra(DatePickerFragment.EXTRA_DATE); 7 mCrime.setmDate(date); 8 if (requestCode == REQUEST_DATE) { 9 //因为TimePicker没有年月日,所以不用专门使用updateTime更新TimePicker 10 updateDate(); 11 } 12 if (requestCode == REQUEST_TIME) { 13 updateTime(); 14 updateDate(); 15 } 16 }
7.运行效果: