Android DialogFragment

时间:2020-02-23 14:28:53  来源:igfitidea点击:

在本教程中,我们将讨论什么是DialogFragments。
在一个简单的android应用程序的帮助下,我们还将看到它们与对话框的不同之处。

Android DialogFragments

DialogFragment是一个实用程序类,它扩展了Fragment类。
它是v4支持库的一部分,用于显示浮动在内容其余部分顶部的活动中的覆盖模式窗口。

本质上,DialogFragment显示一个Dialog,但在Fragment内。

Google建议我们在活动中使用DialogFragment而不是简单的Alert Dialog构建器。

为什么这样?

  • DialogFragments有其自己的生命周期方法。
    因此,活动无需承担告诉对话框该做什么的责任。

  • 没有更多的IllegalStateExceptions和泄漏的窗口崩溃。
    当活动仍在"警报对话框"中被销毁时,这很常见。

由于DialogFragment是片段,因此它集成到活动的生命周期中,并确保对话框窗口中发生的事情保持一致。
使用DialogFragments在Android应用程序中创建对话框是一种很好的做法。

您的类必须扩展DialogFragment并至少实现" onCreateDialog"和/或者" onCreateView"。

您可以通过以下两种方式使用DialogFragment创建对话框:

  • onCreateDialog-在这里您可以使用AlertDialog.Builder类创建AlertDialog。

  • onCreateView-在这里您可以使用定义的自定义视图创建一个对话框。

为了创建一个显示Dialog的DialogFragment,我们需要在DialogFragment实例上调用show()方法:

MyDialogFragment dialogFragment = new MyDialogFragment();
FragmentTranscation 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进行数据传递

为了将数据传递给DialogFragment类,我们可以简单地使用该类实例上的setArguments设置数据。

为了将数据从DialogFragments返回到Activity /另一个片段,我们需要创建自定义接口。

在以下部分中,我们将创建一个执行以下操作的android应用程序:

  • 创建一个简单的DialogFragment对话框

  • 嵌入在Activity中的DialogFragment

  • 带有样式的DialogFragment。

  • 返回数据的DialogFragment

代码

下面给出了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="EMBED DIALOG FRAGMENT" 

  <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="SIMPLE DIALOG FRAGMENT" 

  <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="DIALOG FRAGMENT FULL SCREEN" 

  <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="Alert Dialog Fragment" 

  <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。

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="Please enter your username and password" 

  <EditText
      android:id="@+id/inEmail"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:hint="Email Address"
      android:inputType="textEmailAddress" 

  <EditText
      android:id="@+id/inPassword"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:hint="Password"
      android:inputType="textPassword" 

  <Button
      android:id="@+id/btnDone"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="Done" 
</LinearLayout>

因此,我们的对话框将显示一个基本的登录表单。

MainActivity.java的代码如下:

package com.theitroad.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", "[email protected]");
              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("Email was not entered");
      } else
          textView.setText("Email entered: " + inputText);
  }
}

上面的类实现了接口MyDialogFragment.DialogListener,只要单击DialogFragment的按钮,该接口就会触发onFinishEditDialog方法。
它显示在"活动"对话框中输入的数据。

MyDialogFragment.java类的代码如下:

package com.theitroad.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("Alert Dialog");
      builder.setMessage("Alert Dialog inside DialogFragment");

      builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
          @Override
          public void onClick(DialogInterface dialog, int which) {
              dismiss();
          }
      });

      builder.setNegativeButton("Cancel", 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()函数关闭对话框。