DialogFragment是在Android 3.0时引入的,是一种特殊的Fragment,用于在Activity的内容之上展示一个模拟的对话框。例如,用于展示一个警示框、密码框等。在DialogFragment之前,我们创建对话框,一般都是采用AlertDialog。
相信大家也会有疑问,为什么我们现在不使用AlertDialog,而已采用DialogFragment呢?
使用DialogFragment里管理对话框,当旋转屏幕或者按下返回键时可以更好的管理Dialog的生命周期,它和Fragment有着基本一致的生命周期。
使用DialogFragment其实很简单,我们只需要重写其onCreateView或者onCreateDialog方法即可。其中:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">
<TextView android:text="@string/input_password" android:gravity="center" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp"/>
<EditText android:id="@+id/id_password" android:layout_width="match_parent" android:layout_height="wrap_content" />
<RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content">
<Button android:id="@+id/id_cancel_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="取消" android:layout_alignParentStart="true"/>
<Button android:id="@+id/id_confirm_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="确认" android:layout_alignParentEnd="true"/>
</RelativeLayout>
</LinearLayout>
public class PasswordDialogFragment extends DialogFragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dialog_password, container);
return view;
}
}
private void showPasswordDialog() {
PasswordDialogFragment passwordDialogFragment = new PasswordDialogFragment();
passwordDialogFragment.show(getFragmentManager(), "PasswordDialogFragment");
}
可以看到,dialog已经被成功的创建出来了。可是,默认的对话框上还有一个讨厌的留白,我们可以使用如下代码将其去掉:
public class PasswordDialogFragment extends DialogFragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// 去掉留白的标题栏
getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
View view = inflater.inflate(R.layout.dialog_password, container);
return view;
}
}
在onCreateDialog中可以直接使用AlertDialog或者Dialog创建对话框,不过,既然google官方不建议使用Dialog,我们就使用AlertDialog来创建一个登录对话框。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">
<EditText android:id="@+id/id_user" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="用户名"/>
<EditText android:id="@+id/id_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="密码"/>
</LinearLayout>
public class LoginDialogFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = LayoutInflater.from(getActivity());
View view = inflater.inflate(R.layout.dialog_login, null);
builder.setView(view)
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getActivity(), "确定", Toast.LENGTH_SHORT).show();
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getActivity(), "取消", Toast.LENGTH_SHORT).show();
}
});
return builder.create();
}
}
private void showLoginDialog() {
LoginDialogFragment loginDialogFragment = new LoginDialogFragment();
loginDialogFragment.show(getFragmentManager(), "LoginDialogFragment");
}
效果图:
从Dialog传递数据给Activity,我们可以使用”fragment interface pattern”的方式,以上面的对话框为例,来展示一下实现方法。
在LoginDialogFragment中定义一个接口,并让Activity实现该接口。
public class LoginDialogFragment extends DialogFragment {
private EditText mNameEditText;
private EditText mPasswordEditText;
public interface LoginInputListener {
void onLoginComplete(String name, String password);
}
private LoginInputListener mListener;
public void setOnLoginInputListener(LoginInputListener listener) {
this.mListener = listener;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = LayoutInflater.from(getActivity());
View view = inflater.inflate(R.layout.dialog_login, null);
mNameEditText = (EditText) view.findViewById(R.id.id_user);
mPasswordEditText = (EditText) view.findViewById(R.id.id_password);
builder.setView(view)
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getActivity(), "确定", Toast.LENGTH_SHORT).show();
if (mListener != null) {
mListener.onLoginComplete(mNameEditText.getText().toString(),
mPasswordEditText.getText().toString());
}
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getActivity(), "取消", Toast.LENGTH_SHORT).show();
}
});
return builder.create();
}
}
定义一个Activity,并实现LoginInputListener接口。并且,在实例化LoginDialogFragment时,设置自己为其Listener。
public class MainActivity extends Activity implements LoginDialogFragment.LoginInputListener{
private void showPasswordDialog() {
LoginDialogFragment loginDialogFragment = new LoginDialogFragment();
loginDialogFragment.setOnLoginInputListener(this);
loginDialogFragment.show(getFragmentManager(), "LoginDialogFragment");
}
@Override
public void onLoginComplete(String name, String password) {
Toast.makeText(this, "姓名:" + name + ", 密码:" + password, Toast.LENGTH_SHORT).show();
}
}