DialogFragment对话框的最佳实现方式

DialogFragment实现对话框

对话框在项目正很常见,以前做项目我基本上都是用AlertDialog实现对话框。DialogFragment出现以后,我就很少再用其他方式实现对话框交互了。几乎所有项目中的弹框都通过DialogFragment实现。

这篇文章从以下几个角度总结使用DialogFragment:

  • 生命周期
  • 基本对话框实现
  • Alert Dialog实现

这里写图片描述


DialogFragment的生命周期

DialogFragment做了各种各样的事情来处理碎片的生命周期,DialogFragment需要保证碎片和Dialog显示过程中保持一致的状态,DialogFragment监视从对话框中删除事件,并负责在发生时删除它自己的状态。我们必须使用show方法来为UI添加一个对话片段的实例,当对话框被删除时,这些记录的对话框片段应该被删除。

DialogFragment有完整的生命周期处理,我们不需要关心如何控制其生命周期。

Basic Dialog

DialogFragment作为基本的Dialog使用,我们可以自由扩展其样式,布局。下面是一个DialogFragment的基本用法:

public class MyDialogFragment extends DialogFragment {

    /**
     * 定义一个标识
     */
    private int mNum;

    /**
     * Create a new instance of MyDialogFragment, providing "num"
     * as an argument.
     */
    public static MyDialogFragment newInstance(int num) {
        MyDialogFragment f = new MyDialogFragment();

        // Supply num input as an argument.
        Bundle args = new Bundle();
        args.putInt("num", num);
        f.setArguments(args);

        return f;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mNum = getArguments().getInt("num");
        // Pick a style based on the num.
        int style = DialogFragment.STYLE_NORMAL, theme = 0;
        switch ((mNum-1)%6) {
            case 1:
                style = DialogFragment.STYLE_NO_TITLE;
                break;
            case 2:
                style = DialogFragment.STYLE_NO_FRAME;
                break;
            case 3:
                style = DialogFragment.STYLE_NO_INPUT;
                break;
            case 4:
                style = DialogFragment.STYLE_NORMAL;
                break;
            case 5:
                style = DialogFragment.STYLE_NORMAL;
                break;
            case 6:
                style = DialogFragment.STYLE_NO_TITLE;
                break;
            case 7:
                style = DialogFragment.STYLE_NO_FRAME;
                break;
            case 8:
                style = DialogFragment.STYLE_NORMAL;
                break;
        }

        switch ((mNum-1)%6) {
            case 4:
                theme = android.R.style.Theme_Holo;
                break;
            case 5:
                theme = Theme_Holo_Light_Dialog;
                break;
            case 6:
                theme = Theme_Holo_Light;
                break;
            case 7:
                theme = Theme_Holo_Light_Panel;
                break;
            case 8:
                theme = Theme_Holo_Light;
                break;
        }
        setStyle(style, theme);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_dialog, container, false);
        View tv = v.findViewById(R.id.text);
        ((TextView)tv).setText("Dialog #" + mNum + ": using style "
                + getNameForNum(mNum));

        // Watch for button clicks.
        Button button = (Button)v.findViewById(R.id.show);
        button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // When button is clicked, call up to owning activity.
                ((MainActivity)getActivity()).showDialog();
            }
        });

        return v;
    }

    private String getNameForNum(int mNum){
        String result = "";
        switch (mNum){
            case 4:
                result =  "Theme_Holo";
                break;
            case 5:
                result = "Theme_Holo_Light_Dialog";
                break;
            case 6:
                result = "Theme_Holo_Light";
                break;
            case 7:
                result = "Theme_Holo_Light_Panel";
                break;
            case 8:
                result = "Theme_Holo_Light";
                break;
        }
        return result;
    }
}

代码很简单,包括Fragment的基本初始化方法,onCreate方法中控制对话框显示的样式,onCreateView中实例化对话框的布局。
Activity中使用:


...
private int mStackLevel = 0;
...

public void showDialog() {

        mStackLevel++;

        // DialogFragment.show() will take care of adding the fragment
        // in a transaction.  We also want to remove any currently showing
        // dialog, so make our own transaction and take care of that here.
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
        if (prev != null) {
            ft.remove(prev);
        }
        ft.addToBackStack(null);

        // Create and show the dialog.
        DialogFragment newFragment = MyDialogFragment.newInstance(mStackLevel);
        newFragment.show(ft,"dialog");
    }

同样通过Fragment的事务进行管理,使用show方法实现展示。


Alert Dialog

上面是通过实现onCreateView方法实现的View,Alert Dialog实现方式是通过实现 onCreateDialog来创建对话框。

public class MyAlertDialogFragment extends DialogFragment {

    public static MyAlertDialogFragment newInstance(String title) {
        MyAlertDialogFragment frag = new MyAlertDialogFragment();
        Bundle args = new Bundle();
        args.putString("title", title);
        frag.setArguments(args);
        return frag;
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        String title = getArguments().getString("title");

        return new AlertDialog.Builder(getActivity())
                .setIcon(R.drawable.alert_dialog_icon)
                .setTitle(title)
                .setMessage("这里是内容显示")
                .setPositiveButton("确认",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int whichButton) {
                                ((MainActivity)getActivity()).doPositiveClick();
                            }
                        }
                )
                .setNegativeButton("取消",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int whichButton) {
                                ((MainActivity)getActivity()).doNegativeClick();
                            }
                        }
                )
                .create();
    }
}

Activity中的调用,这里Dialog中点击确认和取消都是调用的Activity中的方法:

void showAlertDialog() {
        DialogFragment newFragment = MyAlertDialogFragment.newInstance(
                "Alert 标题");
        newFragment.show(getSupportFragmentManager(), "dialog");
    }

    public void doPositiveClick() {
        // Do stuff here.
        Log.i("FragmentAlertDialog", "Positive click!");
        Toast.makeText(this ,"确认" ,Toast.LENGTH_SHORT).show();
    }

    public void doNegativeClick() {
        // Do stuff here.
        Log.i("FragmentAlertDialog", "Negative click!");
        Toast.makeText(this ,"取消" ,Toast.LENGTH_SHORT).show();
    }

此外DialogFragment同样可以作为Fragment在Activity中使用,灵活性非常高。


上面是FragmentDialog的基本用法以及核心知识点。下面代码是我在项目中具体的应用:

public class EditFloatValueDialog extends DialogFragment {
    @BindView(R.id.tv_operat_name)TextView operatNameTV;
    @BindView(R.id.et_value)EditText valueET;

    private static String mTitle;
    private static String mOldValue="";

    private MyDialogListener listener;

    public static EditFloatValueDialog newInstance(String title,String oldValue){
        mTitle=title;
        mOldValue=oldValue;
        return new EditFloatValueDialog();
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStyle(DialogFragment.STYLE_NO_TITLE,android.R.style.Theme_Material_Light_Dialog_MinWidth);
        setCancelable(true);
    }

    @Override
    public void onStart() {
        super.onStart();
        Dialog dialog = getDialog();
        if (dialog != null) {
            DisplayMetrics dm = new DisplayMetrics();
            getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
            dialog.getWindow().setLayout((int) (dm.widthPixels * 0.5), ViewGroup.LayoutParams.WRAP_CONTENT);
        }
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View dialogView=inflater.inflate(R.layout.dialog_edit_float,container,false);
        ButterKnife.bind(this,dialogView);

        getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);

        String mTitleStr = mTitle.replace(":","").replace(":","");
        operatNameTV.setText(mTitleStr);

        if(!TextUtils.isEmpty(mOldValue)){
            valueET.setText(mOldValue);
            valueET.setSelection(mOldValue.length());
        }
        return dialogView;
    }

    @OnClick(R.id.btn_save)
    public void dialogClick(){

        if(listener!=null){
            String value=valueET.getText().toString();
            if(TextUtils.isEmpty(value)){
                T.showShort(getActivity(),R.string.edit_empty);
                return;
            }
            dismiss();
            listener.save(value);
        }
    }

    public void setMyDialogListener(MyDialogListener listener){
        this.listener=listener;
    }

}

在onStart中可以随意控制对话框的大小,onCreate中改变对话框的样式,然后通过接口回调事件处理对话框中交互事件。上面实例也是FragmentDialog的最常用的使用方式。


建议大家都是用FragmentDialog来实现对话框显示。

如果有帮助,欢迎留言点赞,谢谢!

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值