Android DialogFragment
在本教程中,我们将讨论什么是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()函数关闭对话框。

