Android对话框片段完全指南:从入门到精通
在本教程中,我们将讨论什么是DialogFragments。我们将通过一个简单的安卓应用程序来看它们与对话框的区别。
Android DialogFragments 安卓对话框片段
DialogFragment是一个实用类,它继承了Fragment类。它是v4支持库的一部分,用于在活动中显示一个浮动在其余内容之上的模态窗口。实质上,DialogFragment显示一个对话框,但在一个Fragment内部显示。
谷歌建议我们在活动中使用DialogFragment而不是简单的AlertDialog构建器。
为什么这样?
- DialogFragments拥有自己的生命周期方法。因此Activity无需承担告诉Dialog该做什么的责任。
- 不再出现IllegalStateException和窗口泄漏崩溃。当Activity被销毁而Alert Dialog仍然存在时,这种情况相当常见。
因为DialogFragment是一个Fragment,它能够融入Activity的生命周期,确保对话窗口中发生的事情保持一致。在你的安卓应用中,使用DialogFragment来创建对话框是一个好的实践。你的类必须继承DialogFragment,并且至少实现onCreateDialog和/或onCreateView。你可以通过两种方式使用DialogFragment来创建对话框。
- onCreateDialog – 在这里你可以使用AlertDialog.Builder类创建AlertDialog。
- onCreateView – 在这里你可以使用定义的自定义视图创建Dialog。
为了创建一个显示对话框的DialogFragment,我们需要在DialogFragment实例上调用show()方法。
MyDialogFragment dialogFragment = new MyDialogFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
dialogFragment.show(ft, "dialog");
我们可以将任何标签设置为show()方法的第二个参数。为了创建一个将对话框嵌入到片段中的DialogFragment,我们只需像对待任何片段一样将片段添加到FrameLayout中即可。
你知道吗?除了对话框,你也可以在片段中显示自定义视图。
当实例化DialogFragment类时,方法按照以下顺序被调用:
- onCreate
- onCreateDialog
- onCreateView
- onViewCreated
- onDestroy
将数据传递给对话框片段并从中返回数据
为了将数据传递给DialogFragment类,我们可以简单地在类的实例上使用setArguments方法设置数据。为了将数据从DialogFragments返回给Activity/另一个片段,我们需要创建自定义接口。在下面的部分中,我们将创建一个Android应用程序,完成以下几个任务:
- 创建一个简单的DialogFragment对话框
- 一个嵌入在Activity中的DialogFragment
- 带有样式的DialogFragment
- 返回数据的DialogFragment
项目结构
代码
这是文章《Android对话框片段》的第2部分(共2部分)。
下面是activity_main.xml类的代码。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/btnEmbedDialogFragment"
android:layout_alignParentTop="true" />
<Button
android:id="@+id/btnEmbedDialogFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_above="@+id/btnDialogFragment"
android:text="嵌入对话框片段" />
<Button
android:id="@+id/btnDialogFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginTop="8dp"
android:text="简单对话框片段" />
<Button
android:id="@+id/btnDialogFragmentFullScreen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/btnDialogFragment"
android:layout_centerHorizontal="true"
android:layout_marginTop="8dp"
android:text="全屏对话框片段" />
<Button
android:id="@+id/btnAlertDialogFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/btnDialogFragmentFullScreen"
android:layout_centerHorizontal="true"
android:layout_marginTop="8dp"
android:text="警告对话框片段" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/btnAlertDialogFragment"
android:layout_centerHorizontal="true" />
</RelativeLayout>
每个按钮都会启动不同类型的DialogFragment。自定义视图的xml布局定义在fragment_sample_dialog.xml文件中,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="请输入您的用户名和密码" />
<EditText
android:id="@+id/inEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="电子邮件地址"
android:inputType="textEmailAddress" />
<EditText
android:id="@+id/inPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="密码"
android:inputType="textPassword" />
<Button
android:id="@+id/btnDone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="完成" />
</LinearLayout>
所以我们的对话框会显示一个基本的登录表单。下面是MainActivity.java的代码。
package com.Olivia.androiddialogfragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements View.OnClickListener, MyDialogFragment.DialogListener {
Button btnEmbedDialogFragment, btnDialogFragment, btnDialogFragmentFullScreen, btnAlertDialogFragment;
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
btnEmbedDialogFragment = findViewById(R.id.btnEmbedDialogFragment);
btnDialogFragment = findViewById(R.id.btnDialogFragment);
btnDialogFragmentFullScreen = findViewById(R.id.btnDialogFragmentFullScreen);
btnAlertDialogFragment = findViewById(R.id.btnAlertDialogFragment);
btnEmbedDialogFragment.setOnClickListener(this);
btnDialogFragment.setOnClickListener(this);
btnDialogFragmentFullScreen.setOnClickListener(this);
btnAlertDialogFragment.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btnEmbedDialogFragment:
MyDialogFragment dialogFragment = new MyDialogFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.frameLayout, dialogFragment);
ft.commit();
break;
case R.id.btnDialogFragment:
dialogFragment = new MyDialogFragment();
Bundle bundle = new Bundle();
bundle.putBoolean("notAlertDialog", true);
dialogFragment.setArguments(bundle);
ft = getSupportFragmentManager().beginTransaction();
Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
dialogFragment.show(ft, "dialog");
break;
case R.id.btnDialogFragmentFullScreen:
dialogFragment = new MyDialogFragment();
bundle = new Bundle();
bundle.putString("email", "xyz@gmail.com");
bundle.putBoolean("fullScreen", true);
bundle.putBoolean("notAlertDialog", true);
dialogFragment.setArguments(bundle);
ft = getSupportFragmentManager().beginTransaction();
prev = getSupportFragmentManager().findFragmentByTag("dialog");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
dialogFragment.show(ft, "dialog");
break;
case R.id.btnAlertDialogFragment:
dialogFragment = new MyDialogFragment();
ft = getSupportFragmentManager().beginTransaction();
prev = getSupportFragmentManager().findFragmentByTag("dialog");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
dialogFragment.show(ft, "dialog");
break;
}
}
@Override
public void onFinishEditDialog(String inputText) {
if (TextUtils.isEmpty(inputText)) {
textView.setText("未输入电子邮件");
} else
textView.setText("输入的电子邮件:" + inputText);
}
}
以上类实现了一个接口MyDialogFragment.DialogListener,当DialogFragment的按钮被点击时触发onFinishEditDialog方法。它在Activity上显示在Dialog中输入的数据。MyDialogFragment.java类的代码如下所示:
package com.Olivia.androiddialogfragment;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
public class MyDialogFragment extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
if (getArguments() != null) {
if (getArguments().getBoolean("notAlertDialog")) {
return super.onCreateDialog(savedInstanceState);
}
}
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("警告对话框");
builder.setMessage("对话框片段中的警告对话框");
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dismiss();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dismiss();
}
});
return builder.create();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_sample_dialog, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final EditText editText = view.findViewById(R.id.inEmail);
if (getArguments() != null && !TextUtils.isEmpty(getArguments().getString("email")))
editText.setText(getArguments().getString("email"));
Button btnDone = view.findViewById(R.id.btnDone);
btnDone.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DialogListener dialogListener = (DialogListener) getActivity();
dialogListener.onFinishEditDialog(editText.getText().toString());
dismiss();
}
});
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("API123", "onCreate");
boolean setFullScreen = false;
if (getArguments() != null) {
setFullScreen = getArguments().getBoolean("fullScreen");
}
if (setFullScreen)
setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_Black_NoTitleBar_Fullscreen);
}
@Override
public void onDestroyView() {
super.onDestroyView();
}
public interface DialogListener {
void onFinishEditDialog(String inputText);
}
}
在 onCreateDialog 中,我们创建一个普通的 AlertDialog。dismiss() 函数用于关闭对话框。以下是该应用的操作输出结果:请注意,在全屏对话框中,输入字段的数据已经传递。这就是本教程的结束。您可以点击下面的链接下载项目:
安卓对话片段
GitHub 项目链接