Help us understand the problem. What is going on with this article?

kotlinでAlertDialog with Custom Viewを使うときにはまったこと

More than 1 year has passed since last update.

kotlin-android-extensionsって?

findViewByIdを使用せずともxmlファイルとkotlinソースコード間でのビューの関連付けを行ってくれるようになり、

MainActivity.java
Button button = (Button)findViewById(R.id.button)

こんなことをひたすらにしていたJavaとはおさらばし、
xmlで指定したidのままkotlinソースコード上で使えるという割と便利なプラグイン

今回は、そのことに気づかずにAlertDialogでハマってしまったので、メモ程度に残しておきたいと思います。

何にハマったのか

dialog_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

</LinearLayout>
MainActivity.kt
/* 
package、インポートなどは省略
*/

class MainActivity : AppCompatActivity(), View.OnClickListener {

    private val TAG: String = "MainActivity"

    private val mContext: Context = this

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

        button.setOnClickListener(mContext)
    }

    override fun onClick(view: View?) {
        // customViewとなるViewをinflateして作成
        val customLayout = layoutInflater.inflate(R.layout.component_time_table_dialog, null)
        // inflateしてできたViewから、リソースID参照してEditTextを指定する
        val editText: EditText = customLayout.findViewById(R.id.editText)
        // Builderメソッドで、AlertDialogをビルドする
        AlertDialog.Builder(mContext).apply {
            setView(customLayout)
            setTitle("AlertDialogTutorial")
            setPositiveButton("ACCEPT", DialogInterface.OnClickListener { dialogInterface, which ->
                Toast.makeText(mContext, subject.text.toString(), Toast.LENGTH_SHORT).show()
            })
            setNegativeButton("REJECT", null)
            show()
        }
    }
}

こちらが、最終的に完成したコードのサンプルバージョンです。
実際にどこにハマったかというと、

MainActivity.kt
editText: EditText = customLayout.findViewById(R.id.editText)

の部分ですね、

kotlin-android-extensions

を使っていたので最初はxmlファイルから直接(findViewByIdメソッドを使わず)editTextを用いていました。
しかし、それでは、component_time_table_dialog.xmlから参照しているだけで、AlertDialogのCustomViewとして用いるViewの方からは参照していなかったみたいで、常にIllegalStateExceptionを吐かれました。

考えてみれば、当たり前のことでしたが、同じ過ちを侵さないためにもメモとして残しておきます。
inflateしたViewからはkotlin-android-extensionsは参照しないので、注意してください。
AlertDialogのCustomViewとしてinflateしたViewの方から参照してあげないとエラーを吐かれます。

最後に

kotlin-android-extensionsを初めて使ってみてハマったエラーなので、何言ってんだこんなの当たり前じゃないかというお声もあるかもしれません…コードの改善点等ございましたらご指摘お願いいたします。もし今回の投稿が誰かのお役に立てましたら幸いです(_ _)

techtrain
プロのエンジニアを目指すU30(30歳以下)の方に現役エンジニアにメンタリングもらえるコミュニティです。
https://techbowl.co.jp/techtrain/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away