同一activity托管的两个fragment间的数据传递与返回

创建DatePickerFragment

/** * 使用DialogFragment(AlterDialog视图封装在DialogFragment中)而不使用AlertDialog, * 这是Android开发原则推荐。 使用FragmentManager管理对话框,可使用更多配置选项来显示对话框。 * 另外,如果设备发生旋转,独立配置使用的AlterDialog会在旋转后消失 * ,而配置封装在DialogFragment中的AlertDialog则不会有此问题。 */
public class DatePickerFragment extends DialogFragment {
    public static final String EXTRA_DATE = "com.huangfei.criminalintent.date";
    private Date mDate;

    public static DatePickerFragment newInstance(Date date) {
        Bundle bundle = new Bundle();
        bundle.putSerializable(EXTRA_DATE, date);

        DatePickerFragment fragment = new DatePickerFragment();
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        mDate = (Date) getArguments().getSerializable(EXTRA_DATE);

        /** * DatePickerFragment需要使用Date中的信息来初始化DatePicker对象。然而, * DatePicker对象的初始化需要整数形式的月、日、年。 * Date就是个时间戳,它无法直接提供整数形式的月、日、年。需先创建一个Calendar对象 * ,然后用Date对象对其进行配置,即可从Calendar对 象中取回所需信息。 */
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(mDate);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);

        View view = getActivity().getLayoutInflater().inflate(
                R.layout.dialog_date, null);

        DatePicker datePicker = (DatePicker) view
                .findViewById(R.id.dialog_date_datePicker);
        datePicker.init(year, month, day, new OnDateChangedListener() {

            @Override
            public void onDateChanged(DatePicker view, int year,
                    int monthOfYear, int dayOfMonth) {
                mDate = new GregorianCalendar(year, monthOfYear, dayOfMonth)
                        .getTime();

                /** * 为防止设备旋转时发生Date数据的丢失,在onDateChanged(...)方法的尾部, * 我们将Date对象回写保存到了fragment argument中。 */
                getArguments().putSerializable(EXTRA_DATE, mDate);
            }
        });

        /** * Android有3种可用于对话框的按钮:positive按钮、negative按钮、neutral按钮 */
        return new AlertDialog.Builder(getActivity())
                .setTitle(R.string.date_picker_title)// 设置对话框标题
                .setView(view)// 设置对话框布局
                .setPositiveButton(android.R.string.ok, new OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        sendResult(Activity.RESULT_OK);
                    }
                })// 设置对话框按钮
                .create();
    }
}

设置目标Fragment

mDateButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                FragmentManager fm = getActivity().getSupportFragmentManager();
                DatePickerFragment dialog = DatePickerFragment.newInstance(mCrime.getDate());
                /** * 同一Activity中,为了使CrimeFragment能够接受到DatePickerFragment返回的数据,可将CrimeFragment设置为 * DatePickerFragment的目标fragment,可调用方法: * Fragment.setTargetFragment(Fragment, requestCode); * * 目标fragment以及请求码由FragmentManager负责跟踪记录,我们可调用fragment(设置目标fragment的fragment)的 * getTargetFragment()与getTargetRequestCode()方法获取它们。 */
                dialog.setTargetFragment(CrimeFragment.this, REQUEST_DATE);
                /** * 要将DialogFragment添加给FragmentManager管理并放置到屏幕上,可调用DialogFragment实例的以下方法: * show(FragmentManager manager, String tag) * show(FragmentTransaction transaction, String tag) * * string参数可唯一识别存放在FragmentManager队列中的DialogFragment。 */
                dialog.show(fm, DIALOG_DATE);
            }
        });

传递数据给目标fragment

/**
     * 处理同一activity托管的两个fragment间的数据返回时,可借用Fragment.onActivityResult(...)方法。
     * 因此,直接调用目标fragment的Fragment.onActivityResult(...)方法,即可实现数据的回传。
     * 
     */
    private void sendResult(int resultCode) {
        if (getTargetFragment() == null)
            return;

        Intent intent = new Intent();
        intent.putExtra(EXTRA_DATE, mDate);

        getTargetFragment().onActivityResult(getTargetRequestCode(),
                resultCode, intent);
    }

更为灵活的DialogFragment视图展现

手机的屏幕非常有限。因此,通常需要使用一个activity托管全屏的fragment界面,以显示用户输入要求。该子activity会由父activity的fragment以调用startActivityForResult(…)方法启动。子activity销毁后,父activity会收到onActivityResult(…)方法的调用请求,并将之转发给启动子activity的fragment。

平板设备屏幕比较大。因此,以弹出对话框的方式显示信息和接受用户输入通常会更好。这种情况下,应该设置目标fragment并调用对话框fragment的show(…)方法。对话框被取消后,对话框fragment会调用目标fragment的onActivityResult(…)方法。

代码地址

你可能感兴趣的:(Fragment,数据传递,数据返回)