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()
函数关闭对话框。