ListView に自由なレイアウトの表示を行う場合、以下のような手順になると思います。
1) 自分が表示したいレイアウトを作成
2) そのレイアウトに対するデータを保存するクラスを作成
3) そのクラスを扱う専用アダプタを作成
この際、getView メソッドを Override する事になっています。その中で、convertView == null の場合は各行の初回の処理にはなりますが、画面に同時に表示される行以上を作成する事が無いので、getView 内で常にデータをセットする事になっています。という事は、実際に作成されるボタンのインスタンスは最大行数ぶんしか無いので、それぞれのボタンにイベントを設定しても、イベント数そのものが行数ぶんになってしまうので、ボタンが常に正しい行の処理ができるように、ボタンにとっての最新 position をボタン自身に setTag で登録しておきます。
MainActivity.java
package sample.lightbox.listview02; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { private static final String DEBUG_TAG = "ListView :"; MyArrayAdapter adapter = null; // MyArratAdapter 用プライベートクラス private class MyLinkData { String myText; String myUrl; public MyLinkData(String myText, String myUrl) { this.myText = myText; this.myUrl = myUrl; } } // ボタンが3つあるカスタム行をを使った MyLinkData 専用 ArrayAdapter private class MyArrayAdapter extends ArrayAdapter<MyLinkData> { // プライベートなので、コンストラクタに渡す情報はありません public MyArrayAdapter() { // スーパークラスに必要なのは、アクティビティのインスタンスのみ super(MainActivity.this, 0); } // 一般的な getView 内のカスタマイズ @Override public View getView(int position, View convertView, ViewGroup parent) { View rowView = convertView; if (rowView == null) { LayoutInflater inflater = MainActivity.this.getLayoutInflater(); // ボタンが3つある行 rowView = inflater.inflate(R.layout.row, null); } // myText の表示 // Adapter の position の位置のデータを取得して、行の画面にセット ((TextView)rowView.findViewById(R.id.textView)).setText(adapter.getItem(position).myText); Button button = (Button) rowView.findViewById(R.id.button); Button button2 = (Button) rowView.findViewById(R.id.button2); Button button3 = (Button) rowView.findViewById(R.id.button3); // 初回のみイベント登録 if ( button.getTag() == null ) { // ボタン A button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 最新の position を取得 int buttonPosition = (int) v.getTag(); // その position から データを取得 MyLinkData data = adapter.getItem(buttonPosition); Toast.makeText(MainActivity.this,data.myText,Toast.LENGTH_SHORT).show(); } }); // ボタン B button2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 最新の position を取得 int buttonPosition = (int) v.getTag(); // その position から データを取得 MyLinkData data = adapter.getItem(buttonPosition); Log.i(DEBUG_TAG, data.myText); } }); // ボタン C button3.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 最新の position を取得 int buttonPosition = (int) v.getTag(); // その position から データを取得 MyLinkData data = adapter.getItem(buttonPosition); Toast.makeText(MainActivity.this,data.myUrl,Toast.LENGTH_SHORT).show(); } }); } // getView が呼び出されるという事は、その position が最新の状態なのでボタンに保存 // して、ボタンイベント内でその position を使用する button.setTag(position); button2.setTag(position); button3.setTag(position); return rowView; } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // リストビューに表示させる情報 MyLinkData[] myLinks = { new MyLinkData( "SQLの窓", "http://winofsql.jp" ), new MyLinkData( "logical error", "http://logicalerror.seesaa.net/" ), new MyLinkData( "琴線に触れる", "http://heart.winofsql.jp/"), new MyLinkData( "GINPRO", "http://ginpro.winofsql.jp/"), new MyLinkData( "SQLの窓 2", "http://winofsql.jp" ), new MyLinkData( "logical error 2", "http://logicalerror.seesaa.net/" ), new MyLinkData( "琴線に触れる 2", "http://heart.winofsql.jp/"), new MyLinkData( "GINPRO 2", "http://ginpro.winofsql.jp/") }; // リストビュー用のアダプターを作成 adapter = new MyArrayAdapter(); adapter.addAll(myLinks); // リストビューを取得 ListView listView = (ListView) MainActivity.this.findViewById(R.id.listView); // リストビューにデータ( アダプター ) をセット listView.setAdapter(adapter); // リストビューのアイテムがクリックされた時の処理 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { MyLinkData item = adapter.getItem(position); // LogCatに表示 Log.i(DEBUG_TAG, item.myText); Log.i(DEBUG_TAG, item.myUrl); Log.i(DEBUG_TAG, Integer.toString(position)); // URL を開く startActivity( new Intent(Intent.ACTION_VIEW, Uri.parse(item.myUrl)) ); } }); } }
row.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:descendantFocusability="blocksDescendants" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="A" android:id="@+id/button" android:layout_alignParentTop="true" android:layout_alignParentStart="true"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="B" android:id="@+id/button2" android:layout_below="@+id/button" android:layout_alignParentStart="true" android:layout_marginTop="38dp"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="C" android:id="@+id/button3" android:layout_alignBottom="@+id/button2" android:layout_alignParentEnd="true"/> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="New Text" android:id="@+id/textView" android:layout_below="@+id/button" android:layout_alignParentStart="true" android:textSize="25dp" android:layout_marginTop="3dp"/> </RelativeLayout>
あまり必要性を感じませんが、ListView の行そのものをタップした場合も処理を実行できるように、android:descendantFocusability="blocksDescendants" を行の root の要素に設定しています。
|
【Android Studio 1の最新記事】
- Tools クラスを使って Livedoor の お天気Webサービスを呼び出して Google gson でリストビューに一括で投入するとこうなります
- できる限り不必要な記述は省いて simple_list_item_2 を使った 自前クラスを扱う専用 ArrayAdapter(private) でリストビューの表示
- できるだけ難しい事をせずに、Android のリストビューでタイトルをクリックしたらそのページを表示する( 自前のオブジェクトを ArrayAdapter にセットする )
- インターネットからアイコン画像を取得してリストビューを表示する
- Android の AlertDialog を使いやすくする MessageBox クラス
- できるだけ難しい事をせずに、Android のリストビューでタイトルをクリックしたらそのページを表示する
- Android の単純な ListView の ArrayAdapter による応用の効く 4バリエーション と複数項目に即対応できる SimpleAdapter による実装
- Android Studio : インターネット上の画像を取得して、Bitmap か Drawable で ImageView に表示する
- Storage Access Framework のガイドラインに基づく、Android 4.4 とそれ以降における 画像参照
- Android Studio : GET(POST)メソッドで呼び出す際に、PHP 側のセッションを有効にする為に CookieManager を static で使用する
- Android Studio で AsyncTask / Android Studio ならではの操作でコードを楽々作成
- Android Studio : 現在の時間を ライフサイクルのアクティブな時に処理される onStart で表示する( 5.1.1 )
- Android Studio でボタンをクリックして トースト(Toast) を表示する / onClick プロパティと Button へのイベント登録( Listener )
- Google スプレッドシートで、Android Studio の重要な操作のまとめ
- Android Studio で com.example. lightbox. myapplication を jp.winofsql. lightbox. threeButton に変更
- ショートカットキーを使って、Android Studio のコード記述を極限まで楽にする
- Android Studio の 『CTRL + SHIFT + I』(定義の参照) を中心に、少しでも時間短縮
- Android Strudio で行われている『スペルチェック』をオフにする( Typo: In word '.....' という表示 )
- Android Studio と Pleiades Eclipse + Android SDK が参照する Java SE ドキュメントを日本語化する