アンドロイドのダイアログフラグメント
このチュートリアルでは、DialogFragmentとは何かについて説明します。また、シンプルなAndroidアプリケーションを使って、DialogFragmentsとDialogsの違いも確認します。
アンドロイドのダイアログフラグメント
DialogFragmentは、Fragmentクラスを拡張したユーティリティクラスです。これはv4サポートライブラリの一部であり、アクティビティ内に浮かび上がるオーバーレイモーダルウィンドウを表示するために使用されます。基本的に、DialogFragmentはFragment内でDialogを表示します。
Googleは、アクティビティでシンプルなアラートダイアログビルダーの代わりにDialogFragmentを使用することを推奨しています。
なぜですか?
- DialogFragments have their own lifecycle methods. So the Activity is free from the responsibility of telling the Dialog what to do.
- No more IllegalStateExceptions and leaked window crashes. This was pretty common when the activity was destroyed with the Alert Dialog still there.
DialogFragmentはフラグメントであるため、アクティビティのライフサイクルに統合され、ダイアログウィンドウ内で行われる操作が一貫性を持つことを保証します。Androidアプリケーションでダイアログを作成する際には、DialogFragmentを使用することが良いプラクティスです。クラスはDialogFragmentを拡張する必要があり、onCreateDialogと/またはonCreateViewを実装する必要があります。DialogFragmentを使用してダイアログを作成する方法は2つあります。
- onCreateDialog – Here you can create the AlertDialog using the AlertDialog.Builder class.
- onCreateView – Here you can create a Dialog using a custom view defined.
ダイアログを表示するために、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()の第2引数には任意のタグを設定することができます。ダイアログをフラグメントに埋め込むために、通常のフラグメントのようにFramelayoutにそのフラグメントを追加するだけで作成できます。
知っていますか?ダイアログだけでなく、フラグメントでもカスタムビューを表示することができます。
DialogFragmentクラスがインスタンス化されると、以下の順序でメソッドが呼び出されます。
- onCreate
- onCreateDialog
- onCreateView
- onViewCreated
- onDestroy
ダイアログフラグメントにデータを渡す方法とデータを返す方法
データをDialogFragmentクラスに渡すためには、クラスのインスタンスを使用してsetArgumentsでデータを設定するだけです。DialogFragmentからデータをアクティビティ/他のフラグメントに戻すためには、カスタムインターフェースを作成する必要があります。以下のセクションでは、次のことを行うAndroidアプリケーションを作成します。
- Creates a Simple DialogFragment Dialog
- A DialogFragment embedded in the Activity
- DialogFragment with a style.
- DialogFragment that returns data
プロジェクトの構造
コード
以下に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.scdev.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("Email was not entered");
} else
textView.setText("Email entered: " + inputText);
}
}
上記のクラスは、ボタンがクリックされるたびにメソッドonFinishEditDialogをトリガーするMyDialogFragment.DialogListenerインターフェースを実装しています。ダイアログで入力されたデータをアクティビティ上に表示します。MyDialogFragment.javaクラスのコードは以下の通りです。
package com.scdev.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()関数はダイアログを閉じます。上記のアプリケーションの実行結果は以下の通りです:全画面のダイアログでは、入力フィールドのデータがすでに渡されていることに注意してください。これでチュートリアルは終了です。プロジェクトは以下のリンクからダウンロードできます。
アンドロイドダイアログフラグメント
「GitHubのプロジェクトリンク」