ダイアログからイベントを渡そう ~Android Studio の使い方解説【図解、サンプルコード付き】~

Android アプリ開発基礎 〜 java〜

※本記事は2021年7月2日に更新しました。

「ダイアログからメインアクティビティへイベントを渡すにはどうすればいい?」

本記事ではそんな疑問にお答えします。
まずは次の動画をご覧ください。

ダイアログの押したボタンに応じて「~が押されました」と画面に表示するアプリです。
このアプリを作るには、ダイアログのボタンが押された後、
メインアクティビティで処理を行う必要があります。

このことをダイアログからメインアクティビティへイベントを渡す、と呼びます。
今回はこのイベントの渡し方について解説します。

前提として、本記事はAndroid Studio 4.2.1を対象に記載します。
また、筆者のAndroid Studioは日本語化しているため、日本語にて解説します。

本記事の使用言語はJavaとなります。
今回はProgate のJavaのレッスンがすべて理解できている、
という前提の上進めていきます。
また、今回インターフェースの概念が出てきます。
ご注意ください。

では早速参りましょう!

前回の記事はこちら
ダイアログの表示のさせ方について解説しています。

イベントの渡し方について

イベントの渡し方について解説します。

ダイアログのボタンが押された際にMainActivityにイベントを渡すには、
以下の手順を取ります。

  1. インターフェースを定義し、MainActivityにて実装
  2. onAttachでインターフェースのインスタンスを生成
  3. リスナにて各ボタンが押されたときのメソッドを呼び出し
  4. MainActivityで定義したメソッドが実行

図で表すと以下の通りです。

ポイントは、ボタンが押されたときのメソッドの名前の定義をDialogFragmentで行い、
メソッドの中身をMainActivityで定義することです。
これによりMainActivityの中にあるTextView等を参照することができます。

上記手順について、一つ一つ解説していきます。

インターフェースを定義し、MainActivityにて実装装

SampleDialogFragmentの中で、インターフェースNoticeDialogListenerを定義します。
定義したインターフェースをMainActivityにて実装します。
これにより、インターフェース内のメソッドをMainActivityにて定義することができます。

インターフェースNoticeDialogListenerの定義は以下の通りです。

public interface NoticeDialogListener {
        public void onDialogPositiveClick(DialogFragment dialog);
        public void onDialogNegativeClick(DialogFragment dialog);
        public void onDialogNeutralClick(DialogFragment dialog);
    }

また、MainActivityのインターフェース実装文は以下の通りとなります。

public class MainActivity extends AppCompatActivity

        implements SampleDialogFragment.NoticeDialogListener

{

onAttachでインターフェースのインスタンスを生成

onAttachメソッドの中で、インターフェースのインスタンスを生成します。
onAttachメソッドはダイアログの作成時に一番最初に呼ばれるメソッドです。
このメソッドでインスタンスを作成しておくことで、
後々インスタンスのメソッドを呼び出すことが可能となります。

※インスタンスはメソッドをまたいで使用するため、
 メソッドの外側で定義します。

また、インスタンスをContext(現在のActivity)にて作成することで、
現在のActivity内のViewを使用することが可能となります。

onAttachの中身は以下の通りです。

NoticeDialogListener listener;
@Override
    public void onAttach(Context context) {
        super.onAttach(context);
            listener = (NoticeDialogListener) context;
    }

リスナにて各ボタンが押されたときのメソッドを呼び出し

ダイアログのボタンクリックのリスナにて、各ボタンの押されたときのメソッドを呼び出します。
今回は3つのボタンがあるため、
ボタンのIDにて押されたボタンを判別し、switch文にて条件分岐する、
という方法を取ります。

リスナの定義文は以下の通りです。

    private class DialogClickListener implements DialogInterface.OnClickListener{

        @Override
        public void onClick(DialogInterface dialog,int buttonId){

            //switchにてタップされたボタンでの条件分岐を行う
            switch(buttonId){
                //OKボタンがタップされたとき
                case DialogInterface.BUTTON_POSITIVE:
                    //OKボタンが押されたときのメソッドを呼び出し
                    //処理は継承先のMainActivityで実行
                    listener.onDialogPositiveClick(SampleDialogFragment.this);
                    break;
                //Cancelボタンがタップされたとき
                case DialogInterface.BUTTON_NEGATIVE:
                    //Cancelボタンが押されたときのメソッドを呼び出し
                    //処理は継承先のMainActivityで実行
                    listener.onDialogNegativeClick(SampleDialogFragment.this);
                    break;
                //Neutralボタンがタップされたとき
                case DialogInterface.BUTTON_NEUTRAL:
                    //Neutralボタンが押されたときのメソッドを呼び出し
                    //処理は継承先のMainActivityで実行
                    listener.onDialogNeutralClick(SampleDialogFragment.this);
                    break;
            }

        }
    }

MainActivityで定義したメソッドが実行

最後に呼び出されるメソッドの中身をMainActivity内で定義しておきます。

今回の3つのボタンで行われる動作は

  1. 押されたボタンに応じ、文章を格納
  2. テキストビューの取得
  3. テキストビューに文章を設置

の3つです。
これらをコードにすると以下の通りとなります。

    //ダイアログでボタンが押されたときに動作するコールバック関数を定義
    @Override
    public void onDialogPositiveClick(DialogFragment dialog) {
        //OKメッセージの格納
        String message = getString(R.string.comment_ok);
        TextView textView = findViewById(R.id.textView);
        //TextViewにメッセージを設定
        textView.setText(message);
    }

    @Override
    public void onDialogNegativeClick(DialogFragment dialog) {
        //Cancelメッセージの格納
        String message = getString(R.string.comment_cancel);
        TextView textView = findViewById(R.id.textView);
        //TextViewにメッセージを設定
        textView.setText(message);
    }

    @Override
    public void onDialogNeutralClick(DialogFragment dialog) {
        //Neutralメッセージの格納
        String message = getString(R.string.comment_neutral);
        TextView textView = findViewById(R.id.textView);
        //TextViewにメッセージを設定
        textView.setText(message);
    }

以上がダイアログからメインアクティビティへイベントを渡す手順となります。

ダイアログからイベントを渡すアプリの作成

今回のアプリを作成してみましょう。

今回のアプリはGitHubに公開しています。
下記URLの『SampleDialog』です。
是非参考にしてください。

GitHub - Umigishi-Aoi/SampleDialog: Android Studioでのダイアログの使い方です。このプロジェクトは自分のAndroid Studio の勉強の中で作られたものです。この解説は、https://zerokara-app.com/485/ にあります。How to use Dialog in Android Studio. This project is created in studying how to use Android Studio. This Commentary is in https://zerokara-app.com/485/
Android Studioでのダイアログの使い方です。このプロジェクトは自分のAndroid Studio の勉強の中で作られたものです。この解説は、 にあります。How to use Dialog in Android Studio. This project is created in studying how...

サンプルコードを記載します。

文字列リソースファイルstring.xml

<resources>
    <string name="app_name">SampleDialog</string>
    <string name="text_view">Hello World</string>
    <string name="dialog_title">Sample</string>
    <string name="dialog_message">ダイアログのサンプルです</string>
    <string name="dialog_button_ok">OK</string>
    <string name="dialog_button_cancel">Cancel</string>
    <string name="dialog_button_neutral">Neutral</string>
    <string name="comment_ok">OKがタップされました</string>
    <string name="comment_cancel">Cancelがタップされました</string>
    <string name="comment_neutral">Neutralがタップされました</string>
    <string name="button">ダイアログを表示</string>
</resources>

レイアウトファイル activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/text_view"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.java

package com.zerokaraapp.sampledialog;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.DialogFragment;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity

        implements SampleDialogFragment.NoticeDialogListener

{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button = findViewById(R.id.button);
        button.setOnClickListener(new ButtonClickListener());
    }

    private class ButtonClickListener implements View.OnClickListener{
        @Override
        public void onClick(View view){
            //ダイアログフラグメントのオブジェクトを生成
            SampleDialogFragment dialogFragment = new SampleDialogFragment();
            //ダイアログの表示
            dialogFragment.show(getSupportFragmentManager(),"SampleDialogFragment");
        }

    }

    //ダイアログでボタンが押されたときに動作するコールバック関数を定義
    @Override
    public void onDialogPositiveClick(DialogFragment dialog) {
        //OKメッセージの格納
        String message = getString(R.string.comment_ok);
        TextView textView = findViewById(R.id.textView);
        //TextViewにメッセージを設定
        textView.setText(message);
    }

    @Override
    public void onDialogNegativeClick(DialogFragment dialog) {
        //Cancelメッセージの格納
        String message = getString(R.string.comment_cancel);
        TextView textView = findViewById(R.id.textView);
        //TextViewにメッセージを設定
        textView.setText(message);
    }

    @Override
    public void onDialogNeutralClick(DialogFragment dialog) {
        //Neutralメッセージの格納
        String message = getString(R.string.comment_neutral);
        TextView textView = findViewById(R.id.textView);
        //TextViewにメッセージを設定
        textView.setText(message);
    }

SampleDialogFragment.java

package com.zerokaraapp.sampledialog;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;


import androidx.fragment.app.DialogFragment;

public class SampleDialogFragment extends DialogFragment {

    public interface NoticeDialogListener {
        public void onDialogPositiveClick(DialogFragment dialog);
        public void onDialogNegativeClick(DialogFragment dialog);
        public void onDialogNeutralClick(DialogFragment dialog);
    }

    NoticeDialogListener listener;

    //フラグメントができたときにlistenerをインスタンス化
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

            listener = (NoticeDialogListener) context;

    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        //ダイアログを作るためのビルダーを作成
        //ビルダーでタイトルやメッセージを設定できる
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

        //ダイアログのタイトル文を設定
        builder.setTitle(R.string.dialog_title);

        //ダイアログのメッセージ文を設定
        builder.setMessage(R.string.dialog_message);

        DialogClickListener listener = new DialogClickListener();

        //Positive ボタンに表示内容と、リスナを設定
        builder.setPositiveButton(R.string.dialog_button_ok,listener);

        //Negative ボタンに表示内容と、リスナを設定
        builder.setNegativeButton(R.string.dialog_button_cancel,listener);

        //Neutral ボタンに表示内容と、リスナを設定
        builder.setNeutralButton(R.string.dialog_button_neutral,listener);

        //設定したダイアログを作成
        AlertDialog dialog = builder.create();

        //ダイアログをリターン
        return dialog;
    }


    private class DialogClickListener implements DialogInterface.OnClickListener{

        @Override
        public void onClick(DialogInterface dialog,int buttonId){

            //switchにてタップされたボタンでの条件分岐を行う
            switch(buttonId){
                //OKボタンがタップされたとき
                case DialogInterface.BUTTON_POSITIVE:
                    //OKボタンが押されたときのメソッドを呼び出し
                    //処理は継承先のMainActivityで実行
                    listener.onDialogPositiveClick(SampleDialogFragment.this);
                    break;
                //Cancelボタンがタップされたとき
                case DialogInterface.BUTTON_NEGATIVE:
                    //Cancelボタンが押されたときのメソッドを呼び出し
                    //処理は継承先のMainActivityで実行
                    listener.onDialogNegativeClick(SampleDialogFragment.this);
                    break;
                //Neutralボタンがタップされたとき
                case DialogInterface.BUTTON_NEUTRAL:
                    //Neutralボタンが押されたときのメソッドを呼び出し
                    //処理は継承先のMainActivityで実行
                    listener.onDialogNeutralClick(SampleDialogFragment.this);
                    break;
            }

        }
    }

}

※javaファイルについて、1行目packageの部分は人によって異なります。
コピペする場合は2行目以降をコピペしてください。

以上のコードの記載が終わったら、アプリを実行してみましょう。
動画のようにアプリが動けば成功です。

まとめ

ダイアログからメインアクティビティへイベントを渡す方法について解説しました。

この方法を工夫すれば、データの受け渡しなどが可能となります。
ここまでできるとよりアプリらしくなった気がしますよね。

今回の記事が初心者の方の参考になれば幸いです。

次回の記事はこちら

コメント