前人未踏の領域へ Androidアプリ開発編

Androidアプリ開発に関する調査メモ置き場。古い記事にはアプリ以外も含まれます。

Radioボタンリスト型のAlertDialogを作る

要件

AlertDialogから選択をさせたい。その際の選択肢をRadioButtonで表示したいが
どうすればよいか。また、リストを選択した時点ではダイアログを閉じないようにしたい。

対応

  • ViewをRadioButtonで作る
  • Adapterを独自に定義、設定する
  • RadioボタンのクリックイベントをOFFにする
  • Radioボタンのチェックを自前でON/OFFする
ViewをRadioButtonで作る

RadioButton付きのリストは自分で用意する。RadioButtonはTextViewを継承しているので
ArrayAdapterにそのまま渡すことができる。

<!-- layout/list_item_radio_text.xml -->
<android.support.constraint.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="?android:attr/listPreferredItemHeightSmall">

    <RadioButton
        android:id="@+id/radio_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        tools:text="サンプルテキスト" />
</android.support.constraint.ConstraintLayout>
Adapterをセットする

通常はsetAdapterでも良いはずだが、その場合はアイテムを選択した時点でDialogがdismissされる。
これを回避するためにsetSingleChoiceItemsにadapterを渡す

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

    val sampleArray = context.resources.getStringArray(R.array.sample_array) //一覧で使うString配列
    val adapter = ArrayAdapter<String>(context, R.layout.list_item_radio_text, R.id.radio_text, sampleArray)

    val builder = AlertDialog.Builder(activity)
        builder.setSingleChoiceItems(adapter, -1, { dialog, which ->
                   
                })
RadioボタンのクリックイベントをOFFにする

ListViewのアイテムクリックイベントはRadioButtonのチェックイベントに横取りされてしまうため、
イベントが発動しないように細工をする必要がある。

    <RadioButton
        android:focusable="false"
        android:visibility="visible" />
Radioボタンのチェックを自前でON/OFFする

クリックイベントをOFFにしたため、ListViewのonItemClickは呼ばれるようになったが
今度はRadioのチェックのON/OFFを自分で書かないといけない。

class RadioTextListDialog : DialogFragment() {

    var tmpRadio: RadioButton? = null
 val builder = AlertDialog.Builder(activity)
        builder.setSingleChoiceItems(adapter, -1, { dialog, which ->
                    val d = dialog as AlertDialog
                    val v = d.listView.getChildAt(which)
                    val radio = v.findViewById<RadioButton>(R.id.radio_text)
                    radio.isChecked = true
                    //選択されていたものをOFF
                    if (tmpRadio != radio) {
                        tmpRadio?.isChecked = false
                        tmpRadio = radio
                    }
                })


PreferenceFragmentが使えそうだったらそちらを推奨