场景

经常会有一些弹窗的场景,很多时候,我们用的是 AlertDialog 或者 Dialog 来做。

AlertDialog

AlertDialog 本来就是系统封装好的一个弹窗控件,用起来很简单也很舒服,但是定制起来就不是很方便。

Dialog

所以更多的情况是 继承 Dialog 自己来实现一个 Dialog 。

DialogFragment

DialogFragment 是在 3.0 后引入的,是一种特殊的 Fragment。可以理解为是 Dialog 和 Fragment 的融合体。Google 也推荐使用 DialogFragment 来代替 Dialog。

优点:

由于 DialogFragment 继承自 fragment , 所以拥有 Fragment 的什么周期,和 Fragment 的 特性。
所以可以通过 管理 Fragment 的生命周期来控制 Dialog ,也可以通过 Fragment 来监听一些时间,比如 屏幕旋转 和 Back 键 的监听等。

注意点:

其实也是 Fragment 的一个注意点。
传递数据的时候,尽量使用 setArguments() 来传递数据。因为生命周期变化的时候,setArguments() 传递过来的参数会保存起来,重新构建的时候,数据不会丢失。

DialogFragment 使用

可以使用 onCreateDialog() 或者 onCreateView() 来创建 界面,只需要实现一个就可以了。

在使用 onCreateView() 创建的时候,会有一个默认的主题,导致会有空白背景 ,和 标题栏。
onStart() 里面添加下面的代码就可以去掉了。

Dialog dialog = getDialog();
Window window = dialog.getWindow();
window.setBackgroundDrawable(getResources().getDrawable(R.color.transparency));//背景透明
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);           //设置无标题

关于 DialogFragment 的思考

既然 DialogFragment 既可以是 Dialog 也可以是 Fragment 。那 DialogFragment 到底是什么东西呢。

答案是 Dialog , 但是是一个可以感知 Fragment 生命周期的 Dialog。

通过查看源码,可以发现 DialogFragment 其实是在内部维护一个 Dialog ,然后再把 Fragment 创建的 View , 通过 Dialog 的 setContentView() 设置进去。
要显示的时候,也就是调用 DialogFragment 的 show() 方法来显示的时候会传进来一个 FragmentManager 通过这个 FragmentManager 我们的 Dialogfragment 就可以监听到 Fragment 的生命周期了。
让我们看一下源码:

public void show(FragmentManager manager, String tag) {
    mDismissed = false;
    mShownByMe = true;
    FragmentTransaction ft = manager.beginTransaction();
    ft.add(this, tag);
    ft.commit();
}

再看一下几个关键的 方法:

@Override
public void onStart() {
    super.onStart();
    if (mDialog != null) {
        mViewDestroyed = false;
        mDialog.show();
    }
}

现在知道 为什么要在 onStart() 后面才能去掉 背景和 标题了吧?

什么?还不知道?

这里我们是通过 获取到 window 对象,然后把背景设置成透明。
而第一步是要获取到 window 对象,但是 Dialog 是要在 调用 show() 方法后才会添加到 window 里面,我们才能获取到 window 对象。在 onStart 方法里面就调用了 show 方法。

解决思路

既然知道 DialogFragment 是 Dialog , Dialog 又是通过 WindowManager 来添加的一个 window ,那就好办了,通过修改 window 的配置就可以了。

当然,也还是要在 onStart 方法之后 使用。 至于原因嘛,你懂的 ,刚才已经说过了。

Window window = getDialog().getWindow();
window.setLayout(300,200);

当然位置什么的也是可以控制的,也是通过控制 window 来实现的。