前回の続き。今回は、ListViewの行を選択して色替えを行うのと、行の追加と削除です。

サンプルコード: https://github.com/stack3/AndroidListViewSamples

サンプルコードを起動して、ChoiceSingleを選択してください。

01

行を選択すると背景色が変わります。

02

Addボタンを押すと選択した行の下に新たな行が追加されます。

03

Removeボタンを押すと選択した行が削除されます。

04

choice_single_list_item.xml

行のレイアウトXMLです。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical"
  android:padding="16dp" >
  <TextView
    android:id="@+id/textView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="@dimen/large_text_size" />
</LinearLayout>

ChoiceSingleListItemAdapter

getViewメソッドで、チェック状態を見て行の背景色を変更しています。

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
       〜〜〜省略〜〜〜

        ListView listView = (ListView)parent;
        Resources resources = context.getResources();
        if (listView.getCheckedItemPosition() == position) {
            convertView.setBackgroundColor(resources.getColor(R.color.green));
        } else {
            convertView.setBackgroundColor(resources.getColor(R.color.white));
        }

        return convertView;
    }

listView.getCheckedItemPositionで行をクリックしてチェック状態になっているpositionを得られます。このpositionとgetViewで返すべきViewのpositionが一致するなら背景を緑色にしています。そうでなければ白です。

HighlightActivity

行のクリックイベントでAdapterのnotifyDataSetChangedを呼びます。

private OnItemClickListener listViewOnItemClickListener = new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView adapterView, View view, int position, long id) {
        adapter.notifyDataSetChanged();
    }
};

これを呼ばないと行をクリックしても色が変わりません。これを呼ぶとAdapterのgetViewメソッドが呼ばれて現在の選択状態に応じて背景色が設定されます。

Addボタンによる行の追加。

private OnClickListener addButtonOnClickLisetenr = new OnClickListener() {
     @Override
     public void onClick(View view) {
         ListView listView = (ListView)findViewById(R.id.listView);
         int position = listView.getCheckedItemPosition();
         if (position >= 0) {
             adapter.insert("New Item", position + 1);
         } else {
             adapter.add("New Item");
         }
     }
};

ListView#getCheckedItemPositionで選択中の行インデックスを得て、Adapterのinsertを使って追加。選択中でないならaddを使って最後に追加。

Removeボタンによる行の削除。Adapterのremoveを使って選択中の行を削除。

private OnClickListener removeButtonOnClickLisetenr = new OnClickListener() {
    @Override
     public void onClick(View view) {
         ListView listView = (ListView)findViewById(R.id.listView);
         int position = listView.getCheckedItemPosition();
         if (position >= 0) {
             String item = adapter.getItem(position);
             adapter.remove(item);
             // 削除したpositionのチェックを外す。これをしないと範囲外のものがチェックされたままになりうる。
             listView.setItemChecked(position, false);
         }
     }
};

削除した行はListView#setItemCheckedでチェック状態を外すこと。Adapterでの行削除とListViewのチェック状態解除は暗黙には同期しないようです・・・