Androidアプリで、ListViewを表示させようと思った。
と一言書かないといけないくらい、Androidのアプリはわかっていない。
今回表示させたいのは、メニュー画面と思ってもらおう。
タップしたら、別の画面に遷移するという、よくあるやつだ。
AdapterView.OnItemClickListenerをimprementsするなりnewするなりしてonItemClick()を呼んでもらえるようにすると、タップした要素が取ってこれる、というのはわかった。
気になっているのは、そこからどうやって期待する画面に遷移させるか、だ。
タップしたところの文字列が取れるけど、それを比較するのは、なんか嫌だ。
文字列の比較って、最初から最後まで一致することを比較することになると思うので、文字数分のコストがかかってしまう。
それに、何らかの理由で同じ文字列が複数あったら、もうだめだ。
じゃあ、タップしたインデックス値ならどうか。
それだと、値は一意で決まるから、同じ文字列があっても問題はない。
比較するのも1回分のコストで済む。
ただ・・・表示する文字列は<string-array>でやろうと思っているので、書くのはXMLになる。
もし気分が変わってメニューの項目順を変えてしまったら、実装の方も変更しないといかん。
うーん、それは気が進まない・・・。
そこで思ったのが、文字列と値をセットにしたものをListViewに持たせられないか?というもの。
調べてみると、どこかのサイトに、toString()で返す値が表示されるだけだよ、とあった。
class ListData {
public String title;
public int value;public ListData(String title, int value) {this.title = title;
this.value = value;
}@Overridepublic String toString() {
return title;
}}
こういうのでよいみたい。
<string-array name="main_list_label"><item>Read</item><item>Write</item><item>Format</item></string-array><integer-array name="main_list_label_num"><item>1</item><item>2</item><item>3</item></integer-array>
こんなarrayたちを作って、
String[] titles = getResources().getStringArray(R.array.main_list_label);int[] title_nums = getResources().getIntArray(R.array.main_list_label_num);
ListData[] list_data = new ListData[labels.length];
for (int i=0; i<labels.length; i++) {list_data[i] = new ListData(labels[i], title_nums[i]);
}ListView lv = (ListView)findViewById(R.id.listView);ArrayAdapter<ListData> adapter = new ArrayAdapter<ListData>(this, android.R.layout.simple_expandable_list_item_1, list_data);lv.setAdapter(adapter);
こうやってやると、
@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {ListView listView = (ListView)parent;ListData item = (ListData)listView.getItemAtPosition(position);Log.d("TEST", item.title + " : " + item.value);}
こんな感じで取得できた。
できれば、順番的な値じゃなくて、直接起動するActivity名みたいなものを持たせたいと思っている。
まあ、そういうのができるか調べんといかんが、Javaはクラス名なんかもバイナリで持ってるし、AndroidManifest.xmlにもActivity名を書くくらいだから、できるんじゃないのか?
Activity名だったら見た目もわかりやすいし、もしソースと名前が一致してなかったらエラーになってくれるだろうし。
私としては満足だったんだけど、Stack Overflowに同じようなことをしたい人がいた。
http://stackoverflow.com/questions/2265661/how-to-use-arrayadaptermyclass
これがいいんじゃないか、という回答が多かったのは、ArrayAdapterをextendsする方法だった。
toString()を追加するタイプは2番目で、しかもコメントで「だめだだめだー」みたいに書かれてあった。
私にとってはtoString()を追加する方がわかりやすい(し、楽だし)のだが、何か理由があるんだろうか?
また、ArrayAdapterをカスタマイズする方が優れていたとしても、toString()の方がダメっていう理由がよくわかっていない。
そもそも、ListViewから画面遷移をするときにこういう方法はとらないのか?
いろいろと疑問が出てきてしまう。。。
へるぷみー。
最近、あれやったり、これやったりに見えてしまうが、実はそうでもない。
Vuforiaにせよ、FeliCa Lite-Sにせよ、動かす環境でアプリを作ることができないと、魅力は半減だ。
一応うちには、Android端末(Nexus7)とiOS端末(iPad mini old)がある。
Vuforiaだったら、どっちもありなのだが、NFCとなるとAndroidになる。
だから、Androidアプリにもう少し力を入れよう、と思い至ったのだ。
ArrayAdapterをextendsするのがListViewの王道的な使い方で、処理の追加、動きの変更もしやすいのでオススメです。
返信削除toStringは基本的にそのクラス、インスタンスを説明する情報を出力するべきなので、あまりプログラム内で使うべきじゃないって感じです。
捨てコードとか、やっつけ仕事の時はtoStringでもいいかもしれません。
toStringの参考記事
Effective Javaの第3章 項目10のtoStringを常にオーバーライドするをirenkaでやってみる件 - じゅんいち☆かとうの技術日誌 http://d.hatena.ne.jp/j5ik2o/20081211/1228962347
なるほど、Javaとしてのお作法というか、言語仕様の意図があるのですね。
削除理由がわからないと、こういう「王道としては、こう」というやり方と「こっちの方が実装的に楽」があると、
後者を選んでしまうんですよね・・・。
extendsする方でやってみます!