概览
一个显示对话框的Fragment,浮在这个Activity的上方。包含一个基于Fragment状态适当显示的Dialog对象。可以通过DialogFragment的API控制这个对话框的显示、隐藏、销毁,不需要直接调用Dialog的。
重写FragmentDialog类实现onCreateView()给对话框提供内容,或者重写onCreateDialog()创建一个完全自定义的对话框,例如拥有自己内容的AlertDialog。
生命周期
DialogFragment在保持Fragment生命周期的驱动下可以做很多不同的事,代替Dialog。注意Dialog通常是自治的实体–他们是自己的窗口,接收自己的输入事件,自己决定何时销毁(当接收到返回键或其他按键事件)。
DialogFragment需要确定Fragment和Dialog发生的状态保持一致。做到这一点,要监听Dialog的销毁事件,当事件发生时要移除自己的状态。这意味着要使用show(FragmentManager, String)或者show(FragmentTransaction, String)为你的UI添加DialogFragment实例,以便注意Dialog销毁时移除它们。
Basic Dialog
DialogFragment的简单用法是作为Fragment图层的简单浮动容器。下面是一个简单的实现:
public static class MyDialogFragment extends DialogFragment {
int mNum;
/**
* Create a new instance of MyDialogFragment, providing "num"
* as an argument.
*/
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(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 = android.R.style.Theme_Holo_Light_Dialog; break;
case 6: theme = android.R.style.Theme_Holo_Light; break;
case 7: theme = android.R.style.Theme_Holo_Light_Panel; break;
case 8: theme = android.R.style.Theme_Holo_Light; break;
}
setStyle(style, theme);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
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 OnClickListener() {
public void onClick(View v) {
// When button is clicked, call up to owning activity.
((FragmentDialog)getActivity()).showDialog();
}
});
return v;
}
}
在Activity中显示:
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 = getFragmentManager().beginTransaction();
Fragment prev = getFragmentManager().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");
}
移除正在显示的Dialog,通过argument创建一个新的DialogFragment,并在堆栈中以新状态显示出来。当事务提交之后,DialogFragment和Dialog会被摧毁,如果有前一个的话会直接显示出来。注意既然这样,当Dialog从DialogFramgent销毁时应该小心的提交事务。
AlertDialog
除了实现onCreateView(LayoutInflater, ViewGroup, Bundle)在Dialog中生成图层之外,也可以通过onCreateDialog(Bundle)创建自定义Dialog对象。
创建一个AlertDialog是很有用的,它允许你向用户显示由Fragment管理的标准通知。简单实现如下:
public static class MyAlertDialogFragment extends DialogFragment {
public static MyAlertDialogFragment newInstance(int title) {
MyAlertDialogFragment frag = new MyAlertDialogFragment();
Bundle args = new Bundle();
args.putInt("title", title);
frag.setArguments(args);
return frag;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
int title = getArguments().getInt("title");
return new AlertDialog.Builder(getActivity())
.setIcon(R.drawable.alert_dialog_icon)
.setTitle(title)
.setPositiveButton(R.string.alert_dialog_ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
((FragmentAlertDialog)getActivity()).doPositiveClick();
}
}
)
.setNegativeButton(R.string.alert_dialog_cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
((FragmentAlertDialog)getActivity()).doNegativeClick();
}
}
)
.create();
}
}
Activity创建这个Fragment应该有下面的方法来显示和从Fragment接收结果:
void showDialog() {
DialogFragment newFragment = MyAlertDialogFragment.newInstance(
R.string.alert_dialog_two_buttons_title);
newFragment.show(getFragmentManager(), "dialog");
}
public void doPositiveClick() {
// Do stuff here.
Log.i("FragmentAlertDialog", "Positive click!");
}
public void doNegativeClick() {
// Do stuff here.
Log.i("FragmentAlertDialog", "Negative click!");
}
注意既然Fragment没有放在返回栈中,只是作为一个无限期运行的Fragment被添加。因为Dialog通常是模态的,这仍将作为一个返回栈操作,从dialog获取用户输入直到销毁。当Dialog销毁,DialogFragment会自动在FragmentManager中移除它。
对话框和植入框的选择
如果你有一个Fragment在某些情况下作为Dialog显示,某些情况下嵌入大的UI是很有用的,这种情况通常会根据你如何使用Fragment去选择,但是可以通过setShowsDialog(boolean)自定义。
例如,这是一个简单的对话框Fragment:
public static class MyDialogFragment extends DialogFragment {
static MyDialogFragment newInstance() {
return new MyDialogFragment();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.hello_world, container, false);
View tv = v.findViewById(R.id.text);
((TextView)tv).setText("This is an instance of MyDialogFragment");
return v;
}
}
这个Fragment的的一个实例,可以创建和显示对话框
void showDialog() {
// Create the fragment and show it as a dialog.
DialogFragment newFragment = MyDialogFragment.newInstance();
newFragment.show(getFragmentManager(), "dialog");
}
也可以作为图层的内容添加:
FragmentTransaction ft = getFragmentManager().beginTransaction();
DialogFragment newFragment = MyDialogFragment.newInstance();
ft.add(R.id.embedded, newFragment);
ft.commit();