質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
XML

XMLは仕様の1つで、マークアップ言語群を構築するために使われています。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

解決済

1回答

1018閲覧

AndroidのListView内のアイテムにリスナを付けたい

tokumei000

総合スコア17

XML

XMLは仕様の1つで、マークアップ言語群を構築するために使われています。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

0グッド

0クリップ

投稿2020/02/19 16:35

前提・実現したいこと

TextViewとButtonがあるListViewを作成しました。
ボタンが押された時に何かの処理をしたいと考え、ボタンにリスナを付けたのですが、NullPointerExceptionのエラーが発生しました。
動的に生成されるものに対して、このようなリスナの付け方はできないということでしょうか?
また、どのように実装すればボタンにリスナを付けれるのでしょうか?
よろしくおねがいします。

該当のソースコード

MainActivity.kt

kotlin

1class MainActivity : AppCompatActivity() { 2 3 override fun onCreate(savedInstanceState: Bundle?) { 4 super.onCreate(savedInstanceState) 5 setContentView(R.layout.activity_main) 6 7 var itemList : MutableList<String> = mutableListOf("アイテム1", "アイテム2", "アイテム3") 8 val lv = findViewById<ListView>(R.id.lv) 9 val adapter = ArrayAdapter(applicationContext, R.layout.row, R.id.tvItemName, itemList) 10 lv.adapter = adapter 11 12 val button = findViewById<Button>(R.id.lvButton) 13 button.setOnClickListener(object: View.OnClickListener{ 14 override fun onClick(v: View?) { 15 Toast.makeText(applicationContext, "hoge", Toast.LENGTH_SHORT).show() 16 } 17 }) 18 } 19}

activity_main.xml

xml

1<?xml version="1.0" encoding="utf-8"?> 2<ListView 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 android:id="@+id/lv" 5 android:layout_height="match_parent" 6 android:layout_width="match_parent"> 7</ListView>

row.xml

xml

1<?xml version="1.0" encoding="utf-8"?> 2<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:orientation="horizontal" android:layout_width="match_parent" 4 android:layout_height="match_parent"> 5 6 <TextView 7 android:id="@+id/tvItemName" 8 android:layout_width="wrap_content" 9 android:layout_height="wrap_content" /> 10 11 <Button 12 android:id="@+id/lvButton" 13 android:layout_width="wrap_content" 14 android:layout_height="wrap_content" 15 android:text="ボタン" /> 16 17</LinearLayout>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

良くあるご質問です.
ネットにも記事はあると思いますので, 検索されては如何でしょうか.

例えば...
AndroidStudio(kotlin)でListViewを使ったButton、ImageViewの表示

投稿2020/02/19 17:18

jimbe

総合スコア13209

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tokumei000

2020/02/20 15:49

カスタムアダプタを作成することでなんとかボタンにリスナを付けることができました。 しかし、NullPointerExceptionが発生する件について1つ疑問があります。 調べてみると、Activityの持つfindViewById()はそのActivityにセット(setContentView)したレイアウト内から対象のIDが存在するか検索するらしく、この仕様のため掲載したコードではButtonを見つけることができずNullPointerExceptionが発生したと考えられます。 そこで、viewの持つfindViewById()ならいけるのではないかと思いonCreate内の「val button = findViewById<Button>(R.id.lvButton)」を「val button = lv.findViewById<Button>(R.id.lvButton)」としてみたのですが、同じくNullPointerExceptionが発生しました。 公式リファレンスの該当部分を読むといけそうな気がしたのですが、なぜNullPointerExceptionが発生してしまったのでしょうか? https://developer.android.com/reference/android/view/View#findViewById(int)
jimbe

2020/02/21 03:09 編集

確かに, findViewById はその View に属するコンポーネントを id で探します. しかし, ListView は Adapter の返す View を表示するだけで, row.xml のコンポーネントはおろか, row.xml 自体知りません. つまり ListView に row.xml は属していません.
hoshi-takanori

2020/02/21 01:19

実際に ListView の各項目が作られるのは onCreate を抜けてからなので、onCreate の中で lvButton を findViewById しても null です。また、ListView には通常複数の項目があるでしょうから、ListView そのものに対して lvButton を findViewById しても一意に定まりません。
jimbe

2020/02/21 08:48

hoshi-takanori さん: > 各項目が作られるのは onCreate を抜けてから や > 通常複数の項目がある とすると, 「onCreate を抜けてから」「1項目しかなければ」等の『条件が揃えば findViewById が null にならない場合がある』かのように見えますが, そうなのでしょうか. 私は, どのタイミングでも, 項目が幾つであっても, ListView からは row.xml 内の id で findViewById は有効な値を返さない(返せない) と思うのですが.
hoshi-takanori

2020/02/21 09:43

実験すれば分かりますが、MainActivity に ListView と Button を配置して、Button が押されたときに ListView の中の View を findViewById したら(見えてるうちで)最初の項目のものが返ります。もちろん、項目が 0 個なら null ですが。
tokumei000

2020/02/21 13:29

実験してみると、仰る通り見えているうちで最初の項目が取得されました。 Viewの持つfindViewById()でもNullPointerExceptionが発生したのは取得時にListViewに項目が設定されていないことが原因のようですね。 >ListViewの各項目が作られるのはonCreateを抜けてから ListViewの各項目を作るのはAdapterのgetView()だと思うのですが、つまりonCreateを抜けてからgetView()が呼び出されているということでしょうか? getView()について調べてみてもいつ呼び出されるかについての情報を見つけられなかったのですが、「onCreateを抜けてから」というのはどこを見れば(リファレンス等)わかるのでしょうか?
jimbe

2020/02/21 18:03

> 実験すれば分かりますが、(後略) なるほど. ありがとうございます.
hoshi-takanori

2020/02/21 21:43

ListView の全項目は何百、何千になる可能性がありますが、実際に一度に表示できるのはせいぜい十個くらいなので、実際に表示される分だけ必要に応じて View を生成し、スクロールした場合は画面の外に出て見えなくなった View を新しく見えるようになった項目のために使い回す(これが getView の convertView 引数)という処理を行なっています。このため、実際の表示に必要になるまでは View は生成されません。 API のリファレンスには細かいメソッドの使い方は書いてありますが、全体的にどう動くかといった設計思想に関することは書いてありません。リファレンスにそれを書くのは効率が悪いので、まずはちゃんとした解説書を読むことが大事かと。
tokumei000

2020/02/22 03:45

APIのリファレンスに全部書かれているわけではないんですね、ちゃんとした解説書を探してみようと思います。 お二方、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問