はじめに
こんにちは。某学校でプログラミング等の勉強中のサーバーサイドのプログラマーのワタタクです。
今回もAndroid開発していきましょう。
Androidには様々なリストビューの出し方があるので、筆者自身も混乱してきたので魔と寝ていきたいと思います。
対象者
- Javaがなんとなく書ける人。
- Android開発が曖昧だけど多少できる人。
リストビューの基本
リストタップのリスナ
○リストビューをタップした時のリスナクラス : onItemClickListenerインタフェースを実装する。
*このインタフェースはAdapterViewクラスのメンバインタフェース
○リスト設定メソッド
setOnItemClickListener(onItemClickListenerを実装したメンバインタフェースを実装したものを入れる)
タップ要素の取得
1)イベントハンドラ : onItemClick()
引数は4つ
1.AdapterView<?> parent
->タップされたListView全体
2.View view
->タップされた1行分の画面部品
3.int position
->タップされた行番号
*0から始まる
4.long id
->DBのデータをもとにListViewを生成した際の主キーの値
*DBを使わない場合は上のpositionと同じ値
2)データ取得
○タップした行のデータはparentとpositionを使って取得できる
(String)parent.getItemAtPosition(position)
サンプルコード
private class ListItemClickListener implements AdapterView.OnItemClickListener {
public void onItemClick(AdapterView<?> parent, View view, int position, long l) {
String item = (String)parent.getItemAtPosition(position);
Toast.makeText(ListClickSampleActivity.this, show, Toast.LENGTH_SHORT).show();
}
}
静的のリストビュー
1) xmlで作る
<?xml version="1.0" encoding="utf-8"?>
<ListView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/lvMenu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:entries="@array/lv_menu"/>
<?xml version="1.0" encoding="UTF-8" ?>
<resources>
<string name="app_name">リスト選択サンプル</string>
<string-array name="lv_menu">
<item>唐揚げ</item>
<item>ハンバーグ定食</item>
<item>生姜焼き定食</item>
<item>ステーキ定食</item>
<item>野菜炒め定食</item>
<item>回鍋肉定食</item>
<item>麻婆豆腐定食</item>
<item>とんかつ定食</item>
<item>ミンチカツ定食</item>
<item>チキンかつ定食</item>
<item>コロッケ定食</item>
<item>焼き魚定食</item>
<item>焼肉定食</item>
<item>弱肉強食</item>
</string-array>
</resources>
public class ListClickSampleActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_click_sample);
ListView lvMenu = findViewById(R.id.lvMenu);
lvMenu.setOnItemClickListener(ListItemClickListener);
}
AdapterView.OnItemClickListener ListItemClickListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long l) {
String item = (String)parent.getItemAtPosition(position);
String show = "あなたが選んだ定食:" + item;
Toast.makeText(ListClickSampleActivity.this, show, Toast.LENGTH_SHORT).show();
}
};
}
2)Javaコードで作る
<?xml version="1.0" encoding="utf-8"?>
<ListView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/lvPref"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
public class PrefListActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pref_list);
ListView lvPref = findViewById(R.id.lvPref);
List<String> prefList = createPrefectureList();
ArrayAdapter<String> adapter = new ArrayAdapter<>(PrefListActivity.this, android.R.layout.simple_list_item_1, prefList);
lvPref.setAdapter(adapter);
lvPref.setOnItemClickListener(new ListItemClickListener());
}
/**
* 都道府県リストを生成するメソッド。
* @return 都道府県リストオブジェクト。
*/
private List<String> createPrefectureList() {
List<String> prefList = new ArrayList<>();
prefList.add("北海道");
prefList.add("青森県");
prefList.add("岩手県");
prefList.add("宮城県");
prefList.add("秋田県");
prefList.add("山形県");
prefList.add("福島県");
prefList.add("茨城県");
prefList.add("栃木県");
prefList.add("群馬県");
prefList.add("埼玉県");
prefList.add("千葉県");
prefList.add("東京都");
prefList.add("神奈川県");
prefList.add("新潟県");
prefList.add("富山県");
prefList.add("石川県");
prefList.add("福井県");
prefList.add("山梨県");
prefList.add("長野県");
prefList.add("岐阜県");
prefList.add("静岡県");
prefList.add("愛知県");
prefList.add("三重県");
prefList.add("滋賀県");
prefList.add("京都府");
prefList.add("大阪府");
prefList.add("兵庫県");
prefList.add("奈良県");
prefList.add("和歌山県");
prefList.add("鳥取県");
prefList.add("島根県");
prefList.add("岡山県");
prefList.add("広島県");
prefList.add("山口県");
prefList.add("徳島県");
prefList.add("香川県");
prefList.add("愛媛県");
prefList.add("高知県");
prefList.add("福岡県");
prefList.add("佐賀県");
prefList.add("長崎県");
prefList.add("熊本県");
prefList.add("大分県");
prefList.add("宮崎県");
prefList.add("鹿児島県");
prefList.add("沖縄県");
return prefList;
}
/**
* リストが選択されたときの処理が記述されたメンバクラス。
* 第2画面へ処理を移管する。
*/
private class ListItemClickListener implements AdapterView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String prefName = (String) parent.getItemAtPosition(position);
Intent intent = new Intent(PrefListActivity.this, PrefEditActivity.class);
intent.putExtra("selectedPrefNo", position);
intent.putExtra("selectedPrefName", prefName);
startActivity(intent);
}
}
}
動的のリストビュー
SimpleCursorAdapterクラスを使う。
→DB内のデータをもとにリストビューを作りたいときに使う。
引数は6つ
1.コンテキスト
2.リストビューの各行のレイアウトを表すR値
*simple_list_view_item_1で通常いい。
3.Cursorオブジェクト
4.String[] : カラム名の配列
5.int[] : 画面部品のR値の配列
6.0でいい
これをリストビューに表示(登録)する方法
->ListViewクラスのsetAdapterメソッドを使う
サンプルコード
public class MemoListActivity extends AppCompatActivity {
private ListView _lvMemoList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_memo_list);
_lvMemoList = findViewById(R.id.lvMemoList);
_lvMemoList.setOnItemClickListener(new ListItemClickListener());
}
@Override
protected void onResume() {
super.onResume();
DatabaseHelper helper = new DatabaseHelper(MemoListActivity.this);
SQLiteDatabase db = helper.getWritableDatabase();
Cursor cursor = DataAccess.findAll(db);
String[] from = {"title"};
int[] to = {android.R.id.text1};
SimpleCursorAdapter adapter = new SimpleCursorAdapter(MemoListActivity.this, android.R.layout.simple_list_item_1, cursor, from, to, 0);
_lvMemoList.setAdapter(adapter);
}
}
onResume : 画面を更新するメソッド
カスタマイズリスト
SimpleAdapterを使う。
row
リストビューの各行をカスタマイズするには以下の手順をとる。
1) 1行分のレイアウト.xmlファイルを用意する
-> xmlファイルの書き方は通常のレイアウトファイルと同じ
<LinearLayout ... >
<ImageView ... />
<TextView ... />
<TextView ... />
<TextView ... />
</LinearLayout>
*ファイル名はなんでも良い
2) アダプタをnewする時にレイアウトを指定する引数に 1) のファイルのR値を指定する。
(ex.)
new.SimpleAdapter( ..., _list, R.layout.row, ... );
3) アダプタクラスをnewする時の引数toのint配列では 1) のファイル中に記述したidのR値を指定する。
(ex.)
int[] to = {R.id.tvMenuName, R.id.tvMenuPrice}
ViewBinder
(1)ViewBinderとは
row.xmlを使うと、リストビュー先行のレイアウトがカスタマイズできる。
では、データに合わせて、各行の表示内容まで変更するには?
from - toの組み合わせでfromのデータをtoの画面部品に割り当てる処理を自作する (ViewBinderの作成)、手順は以下の通り。
1) SimpleAdapter.ViewBinderインタフェースを実装したクラスを作成する。 -> privateなメンバクラスで良い
2) このクラスのsetViewValue()メソッドに画面部品へのデータの割り当て処理を記述する。(後述)
3) アダプタクラスのsetViewBinder()メソッドにこのクラスをnewしたものを渡す
(ex.)
private class CustomViewBinder implement SimpleAdapter.ViewBinder {
@Override
public boolean setViewValue() {
ここに各行内画面部品のデータ割り当てを記述
}
}
adapter.setViewBinder(new CustomViewBinder());
(2) setViewValue() の引数
setViewValue()のメソッドの引数は以下の3コ。
1. View view : 1 行分の中の画面部品。
2. Object data : 上記で第 1 引数に割り当てるデータ。
3. String textReprosentation : 第 2 引数の内容を文字列化したもの。第二引数が null の場合は、
空白文字列。
(3)setViewValue()内の処理パターン
setViewValue()内は引数 viewのidを使って分岐し、引数 data を使って処理を記述していく。
→ switch 文が便利。
public booelan setViewValue ( .... ) {
int viewId = view.getId(); ← id を取得
switch( viewId ) { ← id に応じて処理を分岐 (switch)
case R . id . imPhoneType : ← id 同士の比較なので R 値
ImageView imPhoneType = ( ImageView ) view;
int phoneType = ( Integer ) data;
あとはお好きに。
return true;
case .....
}
return false
}
setViewValue() メソッド内では、ビューにデータを埋め込む独自処理を記述した場合、つまり、各 case の末尾に return true を記述する。さらに、メソッド末尾に return false を記述する。 → この戻り値の値によって、os 側でデータの埋め込み処理を行うかどうかの判定を行なっている。
(4) SimpleCursorAdapter の場合
SimpleCursorAdapter の場合でも、ViewBinder の setViewValue() の処理は SimpleAdapter と同じ。
view . getId() の値を switch で分岐させる。ただし、引数は以下の 3 コ。
1. View view : リスト 1 行中の画面部品。
2. Cursor cursor : 対象となっているリスト 1 行分のデータが格納されたカーソルオブジェクト。
3. int columnIndex : 上記第 1 引数に割り当てるデータのカラムインデックス。
DBデータのリロード
リストビューの元データとなる DB 内のデータが更新された場合、DB からデータを取り直して再表示させる必要がある。
○以下のソースコードとなる。
SimpleCursorAdapter adapter = ( SimpleCursorAdapter ) _lvPhones . getAdapter();
adapter . changeCursor( cursor ); ← カーソルの入れ替え。 新しいカーソル
(注)
onCreate() でアダプタの設定を行い、onResume() でカーソルの設定 ( 入れ替え ) を行うよう な場合、 onCreate() 内で SimpleCursorAdapter を new する際の引数 cursor には null を渡せば良い。
サンプルコード1
public class CustomizedListView2Activity extends AppCompatActivity {
/**
* リストビューに表示させるリストデータ。
*/
private List<Map<String, Object>> _list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_customized_list_view2);
_list = createList();
String[] from = {"phoneType", "phoneNo", "phoneSex"};
int[] to = {R.id.imPhoneType, R.id.tvPhoneNo, R.id.tvSex};
SimpleAdapter adapter = new SimpleAdapter(CustomizedListView2Activity.this, _list, R.layout.row, from, to);
adapter.setViewBinder(new CustomViewBinder());
ListView lvPhones = findViewById(R.id.lvPhones);
lvPhones.setAdapter(adapter);
}
/**
* リストビューに表示されるリストデータを生成するメソッド。
*
* @return 生成されたリストデータ。
*/
private List<Map<String, Object>> createList() {
List<Map<String, Object>> list = new ArrayList<>();
for (int i = 1; i <= 30; i++) {
int phoneType = (int) (3 * Math.random()) + 1;
int phoneNoInt = (int) (99999999 * Math.random());
int phoneSexInt = (int) (10*Math.random() + 1);
String phoneNo = "090" + String.format("%08d", phoneNoInt);
int phoneSex = 1;
if(phoneSexInt <= 5) {
phoneSex = 0;
}
Map<String, Object> map = new HashMap<>();
map.put("phoneType", phoneType);
map.put("phoneNo", phoneNo);
map.put("phoneSex", phoneSex);
list.add(map);
}
return list;
}
/**
* リストビューのカスタムビューバインダークラス。
*/
private class CustomViewBinder implements SimpleAdapter.ViewBinder {
@Override
public boolean setViewValue(View view, Object data, String textRepresentation) {
int viewId = view.getId();
switch(viewId) {
case R.id.imPhoneType:
ImageView imPhoneType = (ImageView) view;
int phoneType = (Integer) data;
switch(phoneType) {
case 2:
imPhoneType.setImageResource(android.R.drawable.ic_menu_crop);
break;
case 3:
imPhoneType.setImageResource(android.R.drawable.ic_menu_myplaces);
break;
default:
imPhoneType.setImageResource(android.R.drawable.ic_menu_call);
break;
}
return true;
case R.id.tvPhoneNo:
TextView tvPhoneNo = (TextView) view;
String phoneNo = (String) data;
tvPhoneNo.setText(phoneNo);
return true;
case R.id.tvSex:
TextView tvSex = (TextView) view;
int phoneSex = (Integer) data;
String sex = "♂";
if(phoneSex == 0) {
sex = "♀";
}
tvSex.setText(sex);
return true;
}
return false;
}
}
}
サンプルコード2
public class CustomizedListView3Activity extends AppCompatActivity {
private ListView _lvPhones;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_customized_list_view3);
_lvPhones = findViewById(R.id.lvPhones);
String[] from = {"phone_type", "phone_no", "phone_sex"};
int[] to = {R.id.imPhoneType, R.id.tvPhoneNo, R.id.tvSex};
SimpleCursorAdapter adapter = new SimpleCursorAdapter(CustomizedListView3Activity.this, R.layout.row, null, from, to, 0);
adapter.setViewBinder(new CustomViewBinder());
_lvPhones.setAdapter(adapter);
}
@Override
public void onResume() {
super.onResume();
setNewCursor();
}
/**
* カーソルアダプタ内のカーソルを更新するメソッド。
*/
private void setNewCursor() {
DatabaseHelper helper = new DatabaseHelper(CustomizedListView3Activity.this);
SQLiteDatabase db = helper.getWritableDatabase();
Cursor cursor = DataAccess.findAll(db);
SimpleCursorAdapter adapter = (SimpleCursorAdapter) _lvPhones.getAdapter();
adapter.changeCursor(cursor);
}
/**
* リストビューのカスタムビューバインダークラス。
*
* @author Shinzo SAITO
*/
private class CustomViewBinder implements SimpleCursorAdapter.ViewBinder {
@Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
int viewId = view.getId();
switch(viewId) {
case R.id.imPhoneType:
ImageView imPhoneType = (ImageView) view;
int phoneType = cursor.getInt(columnIndex);
switch(phoneType) {
case 2:
imPhoneType.setImageResource(android.R.drawable.ic_menu_crop);
break;
case 3:
imPhoneType.setImageResource(android.R.drawable.ic_menu_myplaces);
break;
default:
imPhoneType.setImageResource(android.R.drawable.ic_menu_call);
break;
}
return true;
case R.id.tvPhoneNo:
TextView tvPhoneNo = (TextView) view;
String phoneNo = cursor.getString(columnIndex);
tvPhoneNo.setText(phoneNo);
return true;
case R.id.tvSex:
TextView tvSex = (TextView) view;
int phoneSex = cursor.getInt(columnIndex);
String sex = "♂";
if(phoneSex == 0) {
sex = "♀";
}
tvSex.setText(sex);
return true;
}
return false;
}
}
}
以上。Androidでのリストビューについてまとめて見ました。
もし何か間違っている等のご指摘があればご連絡ください。
最後まで読んで頂きありがとうございました。