创建DialogFragment
将AlertDialog封装在DialogFragment实例中使用,这样FragmentManager管理对话框,可以更灵活地显示对话框。如果旋转设备,单独使用的AlertDialog会消失,而封装在fragment中的AlertDialog不会有此问题。
就CriminalIntent应用来说,我们首先会创建名为 DatePickerFragment 的DialogFragment 子类。然后,在 DatePickerFragment 中,创建并配置显示 DatePicker 组件的 AlertDialog 实例。DatePickerFragment 同样由 CrimePagerActivity 托管。
首先创建DatePickerFragment,并创建AlertDialog:
public class DatePickerFragment extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.date_picker_title)
.setPositiveButton(android.R.string.ok, null)
.create();
}
}
显示DialogFragment
和其他fragment一样,DialogFragment 实例也是由托管activity的 FragmentManager 管理着的。调用fragment实例的show(FragmentManager, String)方法,可将DialogFragment 添加给 FragmentManager 管理并放置到屏幕上。
CrimeFragment.java
private static final String DIALOG_DATE = "DialogDate";
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//...
//在Button上显示日期
mDateButton = view.findViewById(R.id.crime_date);
mDateButton.setText(mCrime.getDate().toString());
mDateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "点击了日期按钮...");
Log.d(TAG, "日期:" + mCrime.getDate().toString());
FragmentManager manager = getFragmentManager();
DatePickerFragment dialog = new DatePickerFragment();
dialog.show(manager, DIALOG_DATE);
}
});
//...
}
设置对话框显示的内容
使用AlertDialog.Builder的setView(View)方法,添加DatePicker组件给
AlertDialog 对话框。该方法配置对话框,实现在标题栏与按钮之间显示传入的View对象。
首先配置DatePicker布局:
dialog_date.xml
<DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/dialog_date_date_picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:calendarViewShown="false">
</DatePicker>
然后添加DatePicker组件给AlertDialog 对话框:
DatePickerFragment.java
public class DatePickerFragment extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
View view = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_date, null);
return new AlertDialog.Builder(getActivity())
.setView(view)
.setTitle(R.string.date_picker_title)
.setPositiveButton(android.R.string.ok, null)
.create();
}
}
fragment间的数据传递
传递数据给DatePickerFragment
DatePickerFragment.java
public static DatePickerFragment newInstance(Date date) {
Bundle args = new Bundle();
args.putSerializable(ARG_DATE, date);
DatePickerFragment fragment = new DatePickerFragment();
fragment.setArguments(args);
return fragment;
}
修改按钮单击事件:
CrimeFragment.onCreateView(LayoutInflater, ViewGroup, Bundle)
mDateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FragmentManager manager = getFragmentManager();
DatePickerFragment dialog = DatePickerFragment.newInstance(mCrime.getDate());
dialog.show(manager, DIALOG_DATE);
}
});
获取Date对象并初始化DatePicker
DatePickerFragment.java
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
Date date = (Date) getArguments().getSerializable(ARG_DATE);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
View view = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_date, null);
mDatePicker = view.findViewById(R.id.dialog_date_date_picker);
mDatePicker.init(year, month, day, null);
return new AlertDialog.Builder(getActivity())
.setView(view)
.setTitle(R.string.date_picker_title)
.setPositiveButton(android.R.string.ok, null)
.create();
}
返回数据给CrimeFragment
设置目标fragment
CrimeFragment.onCreateView(LayoutInflater, ViewGroup, Bundle)
mDateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FragmentManager manager = getFragmentManager();
DatePickerFragment dialog = DatePickerFragment.newInstance(mCrime.getDate());
dialog.setTargetFragment(CrimeFragment.this, REQUEST_DATE);
dialog.show(manager, DIALOG_DATE);
}
});
传递数据给目标fragment
DatePickerFragment.java
public static final String EXTRA_DATE = "com.example.criminalintent.date";
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);
}
DatePickerFragment.onCreateDialog(Bundle)
//...
return new AlertDialog.Builder(getActivity())
.setView(view)
.setTitle(R.string.date_picker_title)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int year = mDatePicker.getYear();
int month = mDatePicker.getMonth();
int day = mDatePicker.getDayOfMonth();
Date date = new GregorianCalendar(year, month, day).getTime();
sendResult(Activity.RESULT_OK, date);
}
})
.create();
响应DatePicker对话框
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);
mDateButton.setText(mCrime.getDate().toString());
Log.d(TAG, "日期已更改 -> " + mCrime.getDate().toString());
}
}