2014/08/30

[android]ListViewに渡したいデータがString[]じゃないときは、ArrayAdapterをextendsする

前回の続き。

しか先生のコメントをいただき、toString()をOverrideするのはJava仕様としてよろしくない、という理解ができた私。
ArrayAdapterをextendsするのがよいとのことなので、やってみよう。


まずどうでもよいことから先に書くと、ListViewのレイアウトをandroid.R.layout.simple_expandable_list_item_1からsimple_list_item_1に変更した。
理由は、expandable、というのが開いたり閉じたりできるタイプだったので、そんな用途もないのでシンプルにしておきたいという理由だけだ。
XMLの中身としてはどっちも同じようなものだったと思う。

ArrayAdapterを拡張する例をネットで調べると、凝ったことをしたい人が多かった。
私のように、単にタイトルの文字列を指定したいだけ、というのがあんまりなさそうだった。
以下は、自分でListView用のXMLを作りたくない人向けになる。

    class MenuAdapter extends ArrayAdapter<ListData> {
        public MenuAdapter(Context context, int resource, ListData[] objects) {
            super(context, resource, objects);
        }
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            TextView view = (TextView)super.getView(position, convertView, parent);
            ListData item = getItem(position);
            if ((view != null) && (item != null)) {
                view.setText(item.title);
            }
            return view;
        }
    }

ListData、というのが、自分で作ったclass。
前回はStringとintだったけど、今回はStringとStringになった。

    class ListData {
        public String title;
        public String actname;
        public ListData(String title, String value) {
            this.title = title;
            this.actname = value;
        }
    }

やってることは・・・単にTextViewにListDataのtitle文字列を設定しているだけだ。
getView()の引数convertViewがTextViewなのは、きっとandroid.R.layout.simple_list_item_1がTextViewを1つしか持っていないからだろう。

最初は、コンストラクタのresourceを保持して、他のArrayAdapterのカスタマイズ記事を見ながらInfraterなどやってたんだけど、うまく行かなかった(今思えば、Infrater後にfindViewByIdでTextViewを探そうとしたところが間違ってたかも)。
convertViewは、非nullなら再描画で使い、nullならInfraterで自作するようだから、じゃあsuperでやってくれるだろう、ということで今の形に落ち着いている。

呼び出し方は前と同じで、こう。

        String[] titles = getResources().getStringArray(R.array.main_list_label);
        String[] actnames = getResources().getStringArray(R.array.main_list_actname);
        ListData[] list_data = new ListData[titles.length];
        for (int i = 0; i < titles.length; i++) {
            list_data[i] = new ListData(titles[i], actnames[i]);
        }
        ListView lv = (ListView) findViewById(R.id.listView);
        MenuAdapter adapter = new MenuAdapter(this, android.R.layout.simple_list_item_1, list_data);
        lv.setAdapter(adapter);

 

私としてはこれでよいと思ってるんだけど、どうかな?

2 件のコメント:

  1. 今回くらいの簡単なListViewの場合は、これでよいと思います!

    以下、本筋とは関係ない補足
    ・変数名list_data は listData にするとJavaっぽいです。
    ・配列list_dataは配列ではなくListクラスを使うとJavaっぽいです。
    List listData = new ArrayList();

    返信削除
    返信
    1. 添削ありがとうございます!

      名前なんですが、メンバ変数(フィールド、と呼ぶんですか)はキャメルにして、ローカル変数は小文字だけにして見分けを付けようかなあ、と思っていました。
      あまりその辺の使い分けは意識しない方がよいですかね?

      配列とListクラスは、数が決まってるから配列の方が軽くてよいかな、と思いました。
      本を読むと、だいたいListでやろう、って出てきますね・・・。

      削除

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。