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 项目链接

bannerAds