使用DialogFragment代替传统Dialog

Android 3.0 引入的基于Fragment的DialogFragment,DialogFragment让dialog也变成了碎片,用于在Activity的内容之上展示一个模态的对话框。
官方推荐使用 DialogFragment 来代替 Dialog ,可以具有更高的可复用性(降低耦合),当旋转屏幕和按下后退键时可以更好的管理其声明周期,和Fragment有着基本一致的声明周期,同时也具有和Fragment一样的优点。

为什么要使用DialogFragment

1、当横竖屏切换时,DialogFragment会自动重建,而AlertDialog没有这样的能力。

如当屏幕方向发生变化,会导致Activity重建,之前显示的AlertDialog对话框就会消失。若要使对话框重建,需手动处理。
在onSaveInstanceState中

1
2
3
4
5
6
7
8
9
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (dialog != null && dialog.isShowing()) {
outState.putBoolean("DIALOG_SHOWN", true);
}else{
outState.putBoolean("DIALOG_SHOWN", false);
}
}

在onCreate中

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
boolean isShown = savedInstanceState.getBoolean("DIALOG_SHOWN");
if (isShown) {
AlertDialog dialog = new AlertDialog.Builder(this).setTitle("Dialog")
.setMessage("this is a dialog").show();
}
}
}

onDestroy()中

1
2
3
4
5
6
7
8
9
/**
* 在Activity销毁之前,确保对话框以关闭,否则会有Android leaked window异常信息
*/
@Override
protected void onDestroy() {
super.onDestroy();
if(dialog != null && dialog.isShowing())
dialog.dismiss();
}

若使用DialogFragment来管理对话框,当旋转屏幕的时候,DialogFragment的对话框将会由FragmentManager自动重建

2、DialogFragment更灵活、松耦合性
DialogFragment可以很灵活的当做普通Fragment使用,在onCreateView中很方便的自定义布局

创建DialogFragment两种方式

1、重写 onCreateDialog
一般用于创建替代传统的 Dialog 对话框的场景。

1
2
3
4
5
6
7
8
9
10
11
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.CustomDialog);
builder.setTitle("title")
.setMessage("this is a dialog")
.setPositiveButton("ok", null)
.setNegativeButton("cancel", null)
.setCancelable(false);
return builder.create();
}

or

1
2
3
4
5
6
7
8
9
10
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.CustomDialog);
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.fragment_dialog, null);
builder.setView(view)
// Do Someting
return builder.create();
}

or

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.fragment_dialog, null);
Dialog dialog = new Dialog(getActivity());
// Dialog dialog = new Dialog(getActivity(), R.style.CustomDialog);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(view);
dialog.setCanceledOnTouchOutside(true);
//Do something
Window window = dialog.getWindow();
window.setBackgroundDrawableResource(R.color.transparent);
WindowManager.LayoutParams wlp = window.getAttributes();
wlp.gravity = Gravity.BOTTOM;
wlp.width = WindowManager.LayoutParams.MATCH_PARENT;
wlp.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(wlp);
return dialog;
}

2、重写 onCreateView
一般用于创建自定义及复杂内容弹窗的场景。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class CustomDialogFragment extends DialogFragment {
public static CustomDialogFragment newInstance(String title) {
CustomDialogFragment frag = new CustomDialogFragment();
Bundle args = new Bundle();
args.putString("title", title);
frag.setArguments(args);
return frag;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NO_TITLE, R.style.CustomDialog);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_custom_dialog, container, false);
// Do Someting
return rootView;
}
}

DialogFragment的管理

1、DialogFactory

可建立一个工厂类对项目中大量的Dialog进行管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class DialogFactory {
private static final String DIALOG_PROGRESS_TAG = "progress";
private static final String DIALOG_ACTION_SHEET_TAG = "action_sheet";
private static final String DIALOG_CONFIRM_TAG = "confirm";
private FragmentManager mFragmentManager;
public DialogFactory(FragmentManager fragmentManager) {
this.mFragmentManager = fragmentManager;
}
public void showProgressDialog(String message, boolean isCancelable) {
if (mFragmentManager != null) {
removeDialogWithTag(DIALOG_PROGRESS_TAG);
ProgressDialogFragment progressDialogFragment = ProgressDialogFragment.newInstance(message, isCancelable);
progressDialogFragment.show(mFragmentManager, DIALOG_PROGRESS_TAG);
mFragmentManager.executePendingTransactions();
}
}
public void dismissProgressDialog() {
Fragment fragment = mFragmentManager.findFragmentByTag(DIALOG_PROGRESS_TAG);
if (null != fragment) {
((ProgressDialogFragment) fragment).dismiss();
mFragmentManager.beginTransaction().remove(fragment).commit();
}
}
private void removeDialogWithTag(String dialogTag){
Fragment fragment = mFragmentManager.findFragmentByTag(dialogTag);
if (null != fragment) {
mFragmentManager.beginTransaction().remove(fragment).commit();
}
}
}

2、链式编程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
public class ConfirmDialogFragment extends BaseDialogFragment {
public interface IDialogClickListener {
void onClick(ConfirmDialogFragment dialog);
}
private IDialogClickListener mPositiveClickListener;
private IDialogClickListener mNegativeClickListener;
public static class Builder {
private Bundle bundle;
private Activity context;
private IDialogClickListener okClickListener;
private IDialogClickListener cancelClickListener;
public Builder(Activity context) {
bundle = new Bundle();
this.context = context;
}
public Builder setTitle(String title) {
putTitle(bundle, title);
return this;
}
public Builder setTitle(int titleId) {
return setTitle(context.getString(titleId));
}
public Builder setMessage(String msg) {
putMessage(bundle, msg);
return this;
}
public Builder setMessage(int msgId) {
return setMessage(context.getString(msgId));
}
public Builder setPositiveButton(int textId, IDialogClickListener l) {
bundle.putString("ok", context.getString(textId));
okClickListener = l;
return this;
}
public Builder setNegativeButton(int textId, IDialogClickListener l) {
bundle.putString("cancel", context.getString(textId));
cancelClickListener = l;
return this;
}
public Builder setCancelable(boolean cancelable) {
putCancelable(bundle, cancelable);
return this;
}
public Builder setCancelableOutside(boolean cancelable) {
putCancelableOutside(bundle, cancelable);
return this;
}
public ConfirmDialogFragment show() {
ConfirmDialogFragment dialog = new ConfirmDialogFragment();
dialog.setArguments(bundle);
dialog.mPositiveClickListener = okClickListener;
dialog.mNegativeClickListener = cancelClickListener;
dialog.show(context.getFragmentManager(), "");
return dialog;
}
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
View view = inflater.inflate(R.layout.fragment_dialog_confirm, container, false);
//...
return view;
}
}

使用时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
new ConfirmDialogFragment.Builder(MainActivity.this)
.setTitle(R.string.dialog_title)
.setMessage(R.string.dialog_message)
.setPositiveButton(R.string.sure, new ConfirmDialogFragment.IDialogClickListener() {
@Override
public void onClick(ConfirmDialogFragment dialog) {
dialog.dismiss();
}
})
.setNegativeButton(R.string.cancel, new ConfirmDialogFragment.IDialogClickListener() {
@Override
public void onClick(ConfirmDialogFragment dialog) {
dialog.dismiss();
}
})
.setCancelable(false)
.setCancelableOutside(false)
.show();