文章目录
- 概述
- 创建 DialogFragment 有两种方式
- 重写 onCreateView 创建Dialog
- 问题一:圆角背景实现
- 重写 onCreateDialog创建 Dialog
- 问题二:数据传递
概述
DialogFragment 在 android 3.0 时被引入。是一种特殊的 Fragment,用于在 Activity 的内容之上展示一个模态的对话框。典型的用于:展示警告框,输入框,确认框等等。
在 DialogFragment 产生之前,我们创建对话框:一般采用 AlertDialog 和 Dialog。注:官方不推荐直接使用 Dialog 创建对话框。
使用 DialogFragment 来管理对话框,当旋转屏幕和按下后退键时可以更好的管理其声明周期,它和 Fragment 有着基本一致的声明周期。且 DialogFragment 也允许开发者把 Dialog 作为内嵌的组件进行重用,类似 Fragment(可以在大屏幕和小屏幕显示出不同的效果)
使用 DialogFragment 至少需要实现 onCreateView
或者 onCreateDIalog
方法。onCreateView
即使用定义的 xml 布局文件展示 Dialog。onCreateDialog
即利用 AlertDialog 或者 Dialog 创建出Dialog
创建 DialogFragment 有两种方式
覆写其 onCreateDialog 方法 — ① 利用 AlertDialog 或者 Dialog 创建出 Dialog
覆写其 onCreateView 方法 — ② 使用定义的 xml 布局文件展示 Dialog
虽然这两种方式都能实现相同的效果,但是它们各有自己适合的应用场景:
方法 ①,一般用于创建替代传统的 Dialog 对话框的场景,UI 简单,功能单一
方法 ②,一般用于创建复杂内容弹窗或全屏展示效果的场景,UI 复杂,功能复杂,一般有网络请求等异步操作
另外它又是 Fragment,所以当旋转屏幕和按下后退键时可以更好的管理其声明周期,它和 Fragment 有着基本一致的声明周期
重写 onCreateView 创建Dialog
a)创建一个布局 fragment_edit_name.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_10_radius"
android:padding="20dp">
<TextView
android:id="@+id/id_label_your_name"
android:layout_width="wrap_content"
android:layout_height="32dp"
android:gravity="center_vertical"
android:text="Your name:" />
<EditText
android:id="@+id/id_txt_your_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/id_label_your_name"
android:imeOptions="actionDone"
android:inputType="text" />
<Button
android:id="@+id/id_sure_edit_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/id_txt_your_name"
android:layout_alignParentRight="true"
android:text="ok" />
</RelativeLayout>
布局整体有一个 10dp 的圆角的紫色背景,即 bg_10_radius.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#9999CC"/>
<corners android:radius="10dp"/>
</shape>
b)继承 DialogFragment,重写 onCreateView 方法
public class EditNameDialogFragment extends DialogFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_edit_name, container, false);
return view;
}
}
c)测试运行
MainActivity 中有 Button,点击弹出刚才的 DialogFragment,点击事件中写如下代码:
EditNameDialogFragment fragment = new EditNameDialogFragment();
fragment.show(getSupportFragmentManager(),"EditNameDialog");
运行结果
问题一:圆角背景实现
通过运行结果可以看到,虽然我们设置了一个 10dp 的圆角,但背景有白色的圆角,这需要我们动态设置背景色为透明色,注意在 xml 布局文件中设置并不会起作用。
我们修改代码:
public class EditNameDialogFragment extends DialogFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_edit_name, container, false);
getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
return view;
}
}
运行结果:
重写 onCreateDialog创建 Dialog
在 onCreateDialog 中一般可以使用 AlertDialog 或者 Dialog 创建对话框,不过既然 google 不推荐直接使用 Dialog,我们就使用 AlertDialog 来创建一个登录的对话框
a)fragment_login_dialog.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="64dp"
android:background="#FFFFBB33"
android:gravity="center"
android:scaleType="center"
android:text="Android App"
android:textColor="@android:color/white" />
<EditText
android:id="@+id/id_txt_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:hint="input username"
android:inputType="textEmailAddress" />
<EditText
android:id="@+id/id_txt_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:fontFamily="sans-serif"
android:hint="input password"
android:inputType="textPassword" />
</LinearLayout>
b)继承 DialogFragment 重写 onCreateDialog 方法
public class LoginDialogFragment extends DialogFragment {
public Dialog onCreateDialog( Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.fragment_login_dialog, null);
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
builder.setView(view)
// Add action buttons
.setPositiveButton("Sign in",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
})
.setNegativeButton("Cancel", null);
return builder.create();
}
}
c)调用
LoginDialogFragment dialog = new LoginDialogFragment();
dialog.show(getSupportFragmentManager(), "loginDialog");
运行结果
问题二:数据传递
MainActivity 向 DialogFragment 传值
Activity 向 DialogFragment 传递数据,采用 setArguments( Bundle )、 getArguments( Bundle ) 方法传递数据。
修改 MainActivity 中打开 DialogFragment 的代码:
LoginDialogFragment dialog = new LoginDialogFragment();
Bundle bundle = new Bundle();
bundle.putString("user_name", "Errol");
dialog.setArguments(bundle);
dialog.show(getSupportFragmentManager(), "loginDialog");
DialogFragment 接收值:
public class LoginDialogFragment extends DialogFragment {
EditText etUserName;
String user_name;
public Dialog onCreateDialog( Bundle savedInstanceState) {
Bundle arguments = getArguments();
if (arguments != null) {
user_name = arguments.getString("user_name");
}
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.fragment_login_dialog, null);
etUserName = view.findViewById(R.id.id_txt_username);
etUserName.setText(user_name);
......
}
}
运行结果
我们从 MainActivity 中向 DialogFragment 传递了 user_name = Errol,DialogFragment 接收到了这个值并进行了显示。
DialogFragment 向 Activity 传值
DialogFragment 向 Activity 传递值可以使用接口。
修改上面的代码
public class LoginDialogFragment extends DialogFragment {
EditText etUserName;
EditText etPassword;
String user_name;
LoginInputListener listener;
public interface LoginInputListener {
void onLoginInputComplete(String name, String passwd);
}
public void setLoginInputListener(LoginInputListener listener){
this.listener = listener;
}
public Dialog onCreateDialog( Bundle savedInstanceState) {
Bundle arguments = getArguments();
if (arguments != null) {
user_name = arguments.getString("user_name");
}
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.fragment_login_dialog, null);
etUserName = view.findViewById(R.id.id_txt_username);
etUserName.setText(user_name);
etPassword = view.findViewById(R.id.id_txt_password);
builder.setView(view)
.setPositiveButton("Sign in",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
listener.onLoginInputComplete(etUserName.getText().toString(),etPassword.getText().toString());
}
})
.setNegativeButton("Cancel", null);
return builder.create();
}
}
MainActivity 中接收:
public class MainActivity extends AppCompatActivity {
Button button;
String user_name = "Errol";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.btn_show);
button.setOnClickListener(v -> {
LoginDialogFragment dialog = new LoginDialogFragment();
Bundle bundle = new Bundle();
bundle.putString("user_name", user_name);
dialog.setArguments(bundle);
dialog.show(getSupportFragmentManager(), "loginDialog");
dialog.setLoginInputListener(new LoginDialogFragment.LoginInputListener() {
public void onLoginInputComplete(String name, String passwd) {
user_name = name;
button.setText(name + " " + passwd);
}
});
});
}
}
运行结果
参考
Android 官方推荐 : DialogFragment 创建对话框