0
点赞
收藏
分享

微信扫一扫

Android DialogFragment总结

十日十月Freddie 2022-04-04 阅读 135

#.简介

    DialogFragment是继承Fragment,兼具Fragment和Dialog的特点:

    一方面,它具有Fragment的生命周期,可以由Activity的FragmentManager来管理器生命周期;

    另一方面,其内部包含一个Dialog成员变量,可以像窗口一样展示。

##.DialogFragment相对于Dialog的优点:

    Dialog的生命周期不会随着Activity生命周期变化而变化,而DialogFragment继承自Fragment,具有与Fragment相同的生命周期和管理方式,FragmentManager会自动管理DialogFragment的生命周期。

    所以在特定场景下,DialogFragment的生命周期管理起来更方便,例如:旋转屏幕等配置变化导致Activity重新创建时,Dialog会消失不见,而DialogFragment会由FragmentManager自动重建。

    谷歌官方推荐使用DialogFragment来代替Dialog。

##使用要点和示例

分析源代码可知,DialogFragment内部包含一个Dialog实例,显示的窗口实际上是这个Dialog实例的窗口。

1. 这个Dialog实例通过onCreateDialog()方法创建,可以覆写该方法,返回自定义的Dialog,如果界面简单的话,其实只覆写该方法就可以实现传统Dialog需要实现的业务。

2. 如果界面复杂的话,则需要在onCreateView()方法中返回需要显示的View,就像普通Fragment中一样。所不同的无非是,在onActivityCreated()中,DialogFragment内部会获取前面返回的View,如果返回的View不是null的话,则会调用mDialog.setContentView(view),将该View设置为Dialog的显示内容。

      也就是说,onCreateDialog()和onCreateView()实际上重写一个就行了,两个都重写是无意义的。如果在onCreateView()中自定了界面,它会覆盖内部Dialog的界面。如果前面在onCreateDialog()中自定义了Dialog的界面,这个界面也会被后面的覆盖掉。

3. 窗口大小的代码逻辑,放在子类的onActivityCreated()、或onStart()、onResume()方法中才会生效。个人习惯放在onActivityCreated()中。

     至于设置窗口大小的方法,与Dialog中类似,都是针对调用Window的api进行设置。

    原因:参考剪藏DialogFragment源码分析 - 简书中的2.4节,如果用onCreateView()来自定义界面,直到onCreateActivity()时,DialogFragment的窗体才被创建出来,因此设置窗口大小的代码逻辑,不能放在更早的生命周期,而是应放在onActivityCreated()、或onStart()、onResume()方法中。

4.通过setStyle()方法设置样式,示例和说明如下:

    setStyle(DialogFragment.STYLE_NO_TITLE, 【自定义的样式,例如R.style.CenterDialog】);

    参数1的有以下值可选:

        STYLE_NORMAL:会显示一个普通的dialog

    STYLE_NO_TITLE:不带标题的dialog

    STYLE_NO_FRAME:无框的dialog

    STYLE_NO_INPUT:无法输入内容的dialog,即不接收输入的焦点,而且触摸无效。

    通过setStyle()设置样式,要在onCreateView之前才有效。一般来讲,都会放到onCreate中调用。

    原因参考剪藏DialogFragment源码分析 - 简书2.2节。

5.显示和隐藏弹窗的方法

    5.1显示

    最简便常用的显示方法:

    RecDialogFragment dialogFragment = RecDialogFragment.newInstance("一个参数”);

    //show()方法的第二个参数是tag,DialogFragment也是一个Fragment,在FragmentManager中会把该DialogFragment与传入的tag绑定在一起,便于后继管理。如果用不到tag,也可以传入空值“”。

    dialogFragment.show(getSupportFragmentManager(), "dialogFragment");

    参考剪藏DialogFragment源码分析 - 简书2.6节。

    5.2隐藏

    使用dismiss() 或 dismissAllowingStateLoss()。

        二者的区别参考剪藏DialogFragment源码分析 - 简书2.6节。

        用前者时有时会出错,故推荐用dismissAllowingStateLoss(),原因参考:DialogFragment 崩溃异常 IllegalStateException:Can not perform this action after onSaveInstanceState - 简书

    (!!!!区别和原因都还没仔细看,有空去看一看,分析一下!!!)

6.在初始化DialogFragment需要传值时,可以像普通Fragment一样通过setArgruments(Bundle)传入值,然后在任意生命周期通过getArgruments()取出值使用。

    对于Fragment,惯有的写法是通常会写一个静态的构建实例的函数,参数为外部需要传入的值:

    public static RecDialogFragment newInstance(String name){

        RecDialogFragment dialogFragment = new RecDialogFragment();

        Bundle bundle = new Bundle();

        bundle.putString("name", name);

        dialogFragment.setArguments(bundle);

        return dialogFragment;

    }    

    取用的示例代码:

    Bundle bundle = getArguments();

    String name = bundle.getString("name");

7.DialogFragment单个实例只能show()一次,再次show()会抛出异常。

    参考剪藏:DialogFragment细枝末节 - 简书

8.可覆写onDissmiss()方法,对DialogFragment的隐藏进行监听。

9.示例代码

public class RecDialogFragment extends DialogFragment {

    public static RecDialogFragment newInstance(String name){

        RecDialogFragment dialogFragment = new RecDialogFragment();

        Bundle bundle = new Bundle();

        bundle.putString("name", name);

        dialogFragment.setArguments(bundle);

        return dialogFragment;

    }

    @Override

    public void onAttach(Context context) {

        super.onAttach(context);

    }

    @Override

    public void onCreate(@Nullable Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        //设置窗口样式

        setStyle(DialogFragment.STYLE_NO_TITLE, R.style.RecCommonDialog);

    }

    private TextView mTvName;

    @Nullable

    @Override

    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        //设置界面

        View view = inflater.inflate(R.layout.dialogfragment_rec, null);

        mTvName = (TextView)view.findViewById(R.id.tv_name);

        view.findViewById(R.id.btn_close).setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

                //隐藏窗口

//                dismiss();

                dismissAllowingStateLoss();

            }

        });

        return view;

    }

    @Override

    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {

        super.onViewCreated(view, savedInstanceState);

    }

    @Override

    public void onActivityCreated(@Nullable Bundle savedInstanceState) {

        super.onActivityCreated(savedInstanceState);

        //设置窗口显示位置、大小

        Dialog dialog = getDialog();

        if(dialog != null){

            Window window = dialog.getWindow();

            window.setGravity(Gravity.CENTER);

            DisplayMetrics dm = getContext().getResources().getDisplayMetrics();

            WindowManager.LayoutParams lp = window.getAttributes();

            lp.width = (int)(dm.widthPixels*0.7);

            lp.height = (int)(dm.heightPixels*0.6);

            window.setAttributes(lp);

        }

    }

    @Override

    public void onStart() {

        super.onStart();

        Bundle bundle = getArguments();

        String name = bundle.getString("name");

        mTvName.setText(name);

    }

    @Override

    public void onResume() {

        super.onResume();

    }

    @Override

    public void onPause() {

        super.onPause();

    }

    @Override

    public void onStop() {

        super.onStop();

    }

    @Override

    public void onDestroyView() {

        super.onDestroyView();

    }

    @Override

    public void onDestroy() {

        super.onDestroy();

    }

    @Override

    public void onDetach() {

        super.onDetach();

    }

    @Override

    public void onDismiss(DialogInterface dialog) {

        super.onDismiss(dialog);

    }

}

参考剪藏:

     DialogFragment源码分析 - 简书 

     DialogFragment细枝末节 - 简书

    

举报

相关推荐

0 条评论