Android权威编程指南笔记 第十二章 对话框Dialog

第十二章 对话框Dialog

Dialog(对话框)

  • 步骤:
  1. 引入相应的依赖项
  2. 创建继承DialogFragment的fragment类
  3. 重写onCreateDialog,并可实例化有关布局。
  4. 借助托管activity的FragmentManager会自动调用onCrea teDialog在屏幕上显示对话框。详情见后面的show方法。使用AlertDialogAlertDialog.Builder(getActivity())可以实现更多个性化需求。
  • 将Dialog封装在对应的Fragment中,可以更加灵活的显示对话框且旋转设备后不会消失。具有ID属性的视图可以保存运行状态。
	return new AlertDialog.Builder(getActivity())
                .setView(v)                             //在DialogFragment中
                .setTitle(R.string.date_picker_title)
                .setPositiveButton(android.R.string.ok, //字符串资源为常量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();

fragment间数据的传递

  • 分为去和回:
  • 去:
  1. fragment中的数据传给另一子fragment时,只要利用Fragment Argument,然后通过getArgument获取内容。
    public static DatePickerFragment newInstance(Date date){
        Bundle args = new Bundle();
        args.putSerializable(ARG_DATE, date);

        DatePickerFragment fragment = new DatePickerFragment();
        fragment.setArguments(args);
        return fragment;
    }
  • 由一个fragment调用另一个fragment需要找到FragmentManager
  • 创建的子fragment需要设置当前fragment 为目标fragment。
  • 创建的子fragment实例调用show()方法。
  1. show(fm, String) 自动创建并提交事物。String 类型的键值对,进行标志。
  2. show(FragmentTrasaction, String) 自己负责创建并提交事物
		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队列中dialog的唯一tag常量标志。	
            }
        });

  • 回 :
    当需要子fragment响应且返回数据时,就需要重写onActivityResult()方法,有如下几点。
  1. 在上面的AlertDialog.Builider 点击监听器中获取相关Intent和结果代码。
  2. 通过调用getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent);调用父类fragment的onActivityResult方法,返回数据
  3. 解析Intent并设置
    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);
    }
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();
        }
    }

相关小记

  • 使用fm管理对话框,可以更灵活的显示对话框。若不使用,如果旋转设备,单独使用的AlertDialog会消失。而具有ID属性的视图可以保存运行状态。
  • DatePicker对象的初始化需将Date形式的数据化为整数形式的 年月日,并将其初始化。
        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 v = LayoutInflater.from(getActivity())
                .inflate(R.layout.dialog_date, null);

        mDatePicker = v.findViewById(R.id.dialog_date_picker);
        mDatePicker.init(year, month, day, null);
  • 将整数形式的数据转化为Date形式
       int year = mDatePicker.getYear();
       int month = mDatePicker.getMonth();
       int day = mDatePicker.getDayOfMonth();
       Date date = new GregorianCalendar(year, month, day).getTime();
  • 可选择覆盖DialogFragment.onCreateView()方法,用于设置全屏fragment,以实现不同设备上的信息显示。

挑战练习

  • 添加TImePickFragment
    DatePickerFragment没多大区别

TimePicker按钮
在这里插入图片描述

package com.bignerdranch.andriod.criminalintent;


import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TimePicker;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;


public class TimePickerFragment extends DialogFragment {


    private static final String ARG_TIME = "time";
    public static final String EXTRA_TIME =
            "com.bignerdranch.andriod.criminalintent.time";

    private TimePicker mTimePicker;

    public static TimePickerFragment newInstance(Date time) {
        Bundle bundle = new Bundle();
        bundle.putSerializable(ARG_TIME, time);

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


    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Date time = (Date) getArguments().getSerializable(ARG_TIME);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        final int year = calendar.get(Calendar.YEAR);
        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);

        View v = LayoutInflater.from(getActivity())
                .inflate(R.layout.fragment_time_picker, null);

         mTimePicker = v.findViewById(R.id.dialog_time_picker);
         mTimePicker.setCurrentHour(hour);
         mTimePicker.setCurrentMinute(minute);

        return new AlertDialog.Builder(getActivity())
                .setView(v)
                .setTitle(R.string.time_picker_title)
                .setPositiveButton(android.R.string.ok,
                        new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        int hour = mTimePicker.getCurrentHour();
                        int minute = mTimePicker.getCurrentMinute();
                        Date time = new GregorianCalendar(year, month, day, hour, minute)
                                .getTime();
                        sendResult(Activity.RESULT_OK, time);
                    }
                })
                .create();
    }

    private void sendResult(int resultOk, Date time) {
        if(getTargetFragment() == null) return;
        Intent intent = new Intent();
        intent.putExtra(EXTRA_TIME, time);

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

  • 挑战练习:实现响应式 DialogFragment
  1. 17章中实现了双版面以后, 传给CrimeFragment启动模式
@Override
public void onCrimeSelected(Crime crime) {
    //手机模式
    if (findViewById(R.id.detail_fragment_container) == null) {
        Intent intent = CrimePagerActivity
                .newIntent(this, crime.getUUID());
        startActivity(intent);
    } else {
        //平板模式
        CrimeFragment fragment = CrimeFragment
                .newInstance(crime.getUUID(), false);  //传给CrimeFragment打开的模式
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.detail_fragment_container, fragment)
                .commit();
    }
}

//在ViewPager中
mViewPager.setAdapter(new FragmentStatePagerAdapter(fragmentManager,
        BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {

    @NonNull
    @Override
    public Fragment getItem(int position) {
        Crime crime = mCrimes.get(position);
        return CrimeFragment.newInstance(crime.getUUID(), true); //手机模式
    }

    @Override
    public int getCount() {
        return mCrimes.size();
    }
});
  • 取出以后判断启动方式
	//CrimeFragment.java中
	mode = (boolean) getArguments().getSerializable(ARG_MODE);

    public void calendarMode(Crime crime){
       if (mode){
           Intent intent = DatePickerActivity	
                   .newIntent(getActivity(), crime.getUUID());
           startActivityForResult(intent, REQUEST_DATE);
       }else {
           datePickerFragment = DatePickerFragment.newInstance(crime.getDate());
           datePickerFragment.setTargetFragment(CrimeFragment.this, REQUEST_DATE);
           datePickerFragment.show(fragmentManager, DIALOG_DATE);
       }
   }

	//实现DatePickerFragment的回调, 移除DatePickerFragment
    @Override
    public void removeCalendar() {
        fragmentManager.beginTransaction().remove(datePickerFragment).commit();
    }
  • 点击确定按钮后
	//DatePickerFragment中
    public void sendResulet(int resultCode, Date date) {
        Intent intent = new Intent();
        intent.putExtra(EXTRA_DATE, date);

        if (getTargetFragment() == null && getActivity() != null) {
            getActivity().setResult(resultCode, intent);
            getActivity().finish();
        } else if (getTargetFragment() != null && getActivity() != null) {
            getTargetFragment()
                    .onActivityResult(getTargetRequestCode(), resultCode, intent);
            if (mCallback != null) {
                mCallback.removeCalendar();
            }
        }
    }

    public interface Callbacks {
        void removeCalendar();
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        if (getTargetFragment() != null) {
            mCallback = (Callbacks) getTargetFragment();
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mCallback = null;
    }

手机

平板

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值