【Android】ダイアログ表示 ~ 基本編 / チェックボックス・ラジオボタン ~

■ はじめに

https://dk521123.hatenablog.com/entry/2013/10/14/002656
https://dk521123.hatenablog.com/entry/2013/10/05/214058
https://dk521123.hatenablog.com/entry/2013/10/06/122942
https://dk521123.hatenablog.com/entry/2013/10/07/005850

の続き。
今回は、チェックボックス/ラジオボタンのダイアログを行う。

目次

【1】ラジオボタン
【2】チェックボックス

【1】ラジオボタン

サンプル (Kotlin / 例1:Hello world)

button.setOnClickListener {
    val targetList = arrayOf("One", "Two", "Three")

    var selectedIndex = -1
    val dialog = AlertDialog.Builder(this)
    dialog.setTitle("Hello World!!")
    dialog.setSingleChoiceItems(targetList, selectedIndex) { _, index ->
        // 選択した項目を保持
        selectedIndex = index
        val value = targetList[selectedIndex]
        Toast.makeText(
            this,
            "Result = $value",
            Toast.LENGTH_SHORT).show()
    }
    dialog.setPositiveButton("OK") { _, _ ->
        if (selectedIndex != -1) {
            val value = targetList[selectedIndex]
            Toast.makeText(
                this,
                "Final Result = $value",
                Toast.LENGTH_SHORT).show()
        } else {
            Toast.makeText(
                this,
                "Please select",
                Toast.LENGTH_SHORT).show()
        }
    }
    dialog.show()
}

サンプル (Kotlin / 例2:音声ファイル一覧)

準備
https://codechacha.com/ja/how-to-use-assets-in-android/

を参考に、、、

[1] [File]-[New]-[Folder]-[Assets Folder]でAssetsフォルダを作成
 => /main/assets ができる
[2] /main/assets を右クリックし、[New]-[Directory] を選択し
 任意のフォルダ名を入力する(今回は「sounds」とする)
[3] /main/assets/<[2]のフォルダ名(sounds)>配下にMP3ファイルを置く

フォルダ構成

└── main
    ├── AndroidManifest.xml
    └── assets
        └── sounds
                 ├── xxxx1.mp
                 ├── xxxx2.mp
                 └── xxxx3.mp

【ダイアログ】SelectSoundDialogFragment.ky

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

class SelectSoundDialogFragment(fileName: String? = null)
    : DialogFragment() {
    interface OnClickListener {
        fun onOkClick(dialog: DialogInterface, fileName: String?)
        fun onCancelClick(dialog: DialogInterface)
    }
    private val defaultSoundIndex = -1

    private var fileName = fileName
    private lateinit var listener: OnClickListener

    override fun onAttach(context: Context) {
        super.onAttach(context)
        if (context is OnClickListener) {
            this.listener = context
        }
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val context = this.context ?: return super.onCreateDialog(savedInstanceState)
        val soundList = getSoundList()
        var selectedIndex = findSoundIndexByFileName(soundList, this.fileName)
        val builder =
            AlertDialog.Builder(context).apply {
                setTitle("Select wake-up sound")
                setSingleChoiceItems(soundList, selectedIndex) { _, index ->
                    selectedIndex = index
                }
                setPositiveButton("OK") { dialog, _ ->
                    val fileName = if (selectedIndex == defaultSoundIndex) {
                        null
                    } else {
                        soundList[selectedIndex]
                    }
                    listener.onOkClick(dialog, fileName)
                }
                setNegativeButton("Cancel") { dialog, _ ->
                    listener.onCancelClick(dialog)
                }
            }

        return builder.create()
    }

    private fun findSoundIndexByFileName(
        soundList: Array<String>, fileName: String?): Int {
        return if (fileName == null) {
            defaultSoundIndex
        } else {
            soundList.indexOf(fileName)
        }
    }

    private fun getSoundList(): Array<String> {
        val sounds = mutableListOf<String>()

        val assetManager = this.resources.assets
        val defaultSounds =
            assetManager.list("sounds") ?: return sounds.toTypedArray()

        for (defaultSound in defaultSounds) {
            if (defaultSound == null ||
                !defaultSound.endsWith(".mp3")) {
                continue
            }
            sounds.add(defaultSound)
        }
        return sounds.toTypedArray()
    }
}

【使用者側】MainActivity.ky

import android.content.DialogInterface
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import xxx.xxx.xxxx.xxxx.SelectSoundDialogFragment
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity(), SelectSoundDialogFragment.OnClickListener {
    private var fileName: String? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        button.setOnClickListener {
            val dialog = SelectSoundDialogFragment(fileName)
            dialog.show(supportFragmentManager, "select_sound")
        }
    }

    override fun onOkClick(dialog: DialogInterface, fileName: String?) {
        this.fileName = fileName
        Toast.makeText(
            this,
            "File Name = $fileName",
            Toast.LENGTH_SHORT).show()
    }

    override fun onCancelClick(dialog: DialogInterface) {
        Toast.makeText(
            this,
            "Cancel",
            Toast.LENGTH_SHORT).show()
    }
}

サンプル (Java)

activity_main.xml

* button x 1、EditText x1 を画面に追加

MainActivity.java

import com.example.dialog.SampleDialogClickHandler;

import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity implements OnClickListener {
    private Button button1;
    private EditText editText1;
    private AlertDialog.Builder dialog;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this.button1 = (Button) findViewById(R.id.button1);
        this.button1.setOnClickListener(this);
        this.editText1 = (EditText)findViewById(R.id.editText1);
        
        String[] items = new String[] {"Java", "C/C++"};
        
        this.dialog = new AlertDialog.Builder(this);
        this.dialog.setTitle("Hello, Title!");
        this.dialog.setIcon(2);
        SampleDialogClickHandler sampleDialogClickHandler =
                new SampleDialogClickHandler(items, this.editText1);
        this.dialog.setSingleChoiceItems(items, 0, sampleDialogClickHandler);
        this.dialog.setPositiveButton("OK", sampleDialogClickHandler);
        this.dialog.setNeutralButton("Cancel", sampleDialogClickHandler);
    }
    
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.button1:
            // ★ここでラジオボタン表示★
            this.dialog.show();
            break;
        }
    }
}

SampleDialogClickHandler.java

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.widget.EditText;

public class SampleDialogClickHandler implements DialogInterface.OnClickListener {
    private String choosedData = null;
    private EditText editText1;
    private String[] items;
    
    public SampleDialogClickHandler(String[] items, EditText editText1) {
        this.items = items;
        this.choosedData = items[0];
        this.editText1 = editText1;
    }

    @Override
    public void onClick(DialogInterface arg0, int arg1) {
        switch(arg1){
        case AlertDialog.BUTTON_NEUTRAL:
            this.choosedData = null;
            this.editText1.setText("Click Cancel.");
            break;
        case AlertDialog.BUTTON_POSITIVE:
            if (this.choosedData != null) {
                this.editText1.setText(String.format("You chose %s", this.choosedData));
            } else {
                this.editText1.setText("Please select something...");
            }
            break;
     default:
            this.choosedData = this.items[arg1];
            this.editText1.setText(String.format("You chose %s", this.choosedData));
            break;
        }
    }
}

【2】チェックボックス

サンプル (Java)

activity_main.xml

* button x 1、EditText x1 を画面に追加

MainActivity.java

import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity implements OnClickListener {
    private Button button1;
    private EditText editText1;
    private AlertDialog.Builder dialog;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this.button1 = (Button) findViewById(R.id.button1);
        this.button1.setOnClickListener(this);
        this.editText1 = (EditText)findViewById(R.id.editText1);
        
        // ★ここ★
        String[] items = new String[] {"Java", "C/C++"};
        boolean[] checkedItems = {false, false};
        
        this.dialog = new AlertDialog.Builder(this);
        this.dialog.setTitle("Hello, Title!");
        this.dialog.setIcon(3);
        SampleMultiChoiceClickHandler sampleMultiChoiceClickHandler =
                new SampleMultiChoiceClickHandler(items, this.editText1);
        this.dialog.setMultiChoiceItems(items, checkedItems, sampleMultiChoiceClickHandler);
        this.dialog.setPositiveButton("OK", sampleMultiChoiceClickHandler);
        this.dialog.setNeutralButton("Cancel", sampleMultiChoiceClickHandler);
    }
    
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.button1:
            // ★ここで表示★
            this.dialog.show();
            break;
        case R.id.button3:
            break;
        case R.id.button4:
            break;
        }
    }
}

SampleMultiChoiceClickHandler.java

import android.content.DialogInterface;
import android.widget.EditText;

public class SampleMultiChoiceClickHandler
    implements DialogInterface.OnMultiChoiceClickListener,DialogInterface.OnClickListener {
    private boolean[] itemBoolValues = { false, false };
    private EditText editText1;
    private String[] items;
    
    public SampleMultiChoiceClickHandler(
            String[] items, EditText editText1) {
        this.items = items;
        this.editText1 = editText1;
    }

    @Override
    public void onClick(DialogInterface arg0, int arg1, boolean isChecked) {
        switch(arg1){
        case 0:
            this.editText1.setText(
                    "Click " + items[arg1] + " isChecked : " + isChecked);
            this.itemBoolValues[0] = isChecked;
            break;
        case 1:
            this.editText1.setText(
                    "Click " + items[arg1] + " isChecked : " + isChecked);
            this.itemBoolValues[1] = isChecked;
            break;
        }
    }

    @Override
    public void onClick(DialogInterface arg0, int arg1) {
        switch(arg1){
        case -3:
            this.itemBoolValues = new boolean[] { false, false };
            this.editText1.setText("Click Cancel.");
            break;
        case -1:
            String message = "";
            int index = 0;
            for (boolean boolValue : this.itemBoolValues) {
                if (boolValue) {
                    message = message + " " + items[index];
                }
                index++;
            }
            if (message != "") {
                this.editText1.setText(String.format("You chose %s", message));
            } else {
                this.editText1.setText("No tech");
            }
            break;
        }
    }
}

参考文献

Kotlin
https://qiita.com/hokutonikukyu/items/ebbc0318c07035e04bf7
https://joyplot.com/documents/2018/01/27/kotlin-alertdialog-choice/

関連記事

ダイアログ表示 ~ 入門編 / トースト・Toast ~
https://dk521123.hatenablog.com/entry/2013/10/14/002656
ダイアログ表示 ~ 基本編 / YES/NO/CANCELボタン ~
https://dk521123.hatenablog.com/entry/2013/10/06/122942
ダイアログ表示 ~ 基本編 / リスト選択 ~
https://dk521123.hatenablog.com/entry/2013/10/07/005850
ダイアログ表示 ~ 基本編 / 日付・時間ダイアログ ~
https://dk521123.hatenablog.com/entry/2020/07/26/000000
アラーム機能を実装するには
https://dk521123.hatenablog.com/entry/2020/07/14/000000