ListFragmentを使ってみる[Android]

#はじめに
　ListFragmentの使い方を勉強。
　基礎の基礎は少し調べればすぐ出るけど、表示するデータは自分で作成したクラスのデータにしたい、ということで検索検索。
　自分なりにまとめてみますことに。
#環境
OS X 10.9.3
Android Studio (Beta) 0.8.0
Sony SOL25 Android 4.4.2(API 19)
#ListFragment
　Fragmentを用いて簡単に(？)Listを表示させることができるモノです、誤解を恐れながら言うと。
　[Fragmentを用いたActionBarによるTab表示](http://qiita.com/mackiso/items/bb3cacac6c0bfb9eb3df)で作成したProjectを参考にしながら、ちょこちょこ変えていきました。
　今回は、タブを2つにし、ひとつをListFragmentとしてTabにSetしました。
　前置きが長い、ザクっと行きます。
##Itemクラス
　サンプルに作った適当なデータクラスです。idと名前を持った簡単なモノですね。

```Item.java
public class Item implements Parcelable{
    public String id;
    public String name;

    public Item(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public Item(Parcel in){
        this.id = in.readString();
        this.name = in.readString();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags){
        dest.writeString(id);
        dest.writeString(name);
    }

    @Override
    public int describeContents() {
        return 0;
    }//FileDescriptor未使用の場合は0

    // 今は定型文という認識で
    public static final Creator<Item> CREATOR = new Creator<Item>() {
        public Item createFromParcel(Parcel in) {
            return new Item(in);
        }

        public Item[] newArray(int size) {
            return new Item[size];
        }
    };
}
```
###Parcelableクラス
　独自にデータクラスを作成した場合に都合がいい模様(適当でごめんなさい)。必要があれば調べてまとめたいところ。
　注意点としては、`writeToParcel(Parcel dest, int flags)`で書き込む順番と`Item(Parcel in)`で読み出す順番を同じにするところだそうです。気をつけよう。
 今回に関してはあまり関係ないです。
##ListFragmentをextendsしたクラス作成
　データを表示するフラグメントですね。今回はListViewだけでは悲しいので、ボタンを3つ設けちゃいました。

```ItemListFragment.java
//import等は割愛

public class ItemListFragment extends ListFragment {

    private ItemListAdapter adapter;

    public ItemListFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //set adapter
        adapter = new ItemListAdapter(getActivity());
        setListAdapter(adapter);
    }

    @Override
    public void onStart() {
        super.onStart();

        this.getView().findViewById(R.id.one).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                adapter.add("1", "button1");
            }
        });
        this.getView().findViewById(R.id.two).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                adapter.add("2", "button2");
            }
        });
        this.getView().findViewById(R.id.three).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                adapter.add("3", "button3");
            }
        });

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.item_listfragment, container, false);
    }

}
```
　ボタンを押すとItemがListViewに追加されるという寸法です。レイアウトも見ていきます。

```item_listfragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="8dp"
    android:paddingRight="8dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/one"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="1"/>
        <Button
            android:id="@+id/two"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="2"/>
        <Button
            android:id="@+id/three"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="3"/>

        </LinearLayout>

    <ListView
        android:id="@id/android:list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:drawSelectorOnTop="false"/>

	//データがない場合に表示される
    <TextView
        android:id="@id/android:empty"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="No data"
        android:textSize="32sp"/>

</LinearLayout>
```
#ListAdapter
　AdapterはListViewとデータをつなげる重要人物です。
　[こちら](http://www18.atwiki.jp/bovecrach/pages/27.html)を参考にさせていただきました。非常に説明が細かくされており、勉強になります。もう、私のよりここをみたほうがよいかも。悲しい。

```ItemListAdapter.java
public class ItemListAdapter extends ArrayAdapter<Item> {

    // 見易さのために定義。普段は直接 getView で指定する。
    private static final int resource = R.layout.custom_listview_item;

    public ItemListAdapter(Context context){
        super(context, 0);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // super.getView() は 呼ばない(カスタムビューにしているため)
        View view;

        // テンプレート処理。
        if (convertView == null) {
            LayoutInflater inflater = LayoutInflater.from(getContext());
            view = inflater.inflate(resource, parent, false);
        } else {
            view = convertView;
        }

        // データをgetItemで取る
        Item item = getItem(position);

        // カスタムビューの場合はViewが確実にあるtry-catch は不要ためか。
        TextView id = (TextView) view.findViewById(R.id.id);
        id.setText(item.id);
        TextView name = (TextView) view.findViewById(R.id.name);
        name.setText(item.name);

        return view;
    }

    // 設定されている CustomListItem の ArrayList を返す。
    // 縦横切替などでデータを移行するために使う。
    public ArrayList<Item> getItemList() {
        // 今回は Bundle#putParcelableArrayList() を使うことを想定する。
        // 必要に応じて Bundle#putSparseParcelableArray() を使ってもいい。

        int size = getCount();
        ArrayList<Item> itemList = new ArrayList<Item>(size);
        for (int index = 0; index < size; index++) {
            itemList.add(getItem(index));
        }
        return itemList;
    }

    // Bundleから復元するときに必要になるはず。
    public void addAll(ArrayList<Item> parcelableArrayList) {
        // 強制でキャスト。落ちる場合は、設計か実装が間違っている。
        @SuppressWarnings("unchecked")
        ArrayList<Item> itemList = (ArrayList<Item>) parcelableArrayList;
        super.addAll(itemList);
    }

    public void add(String id, String name) {
        Item item = new Item(id, name);
        super.add(item);
    }

    // 削除
    public void remove(int index) {
        if (index < 0 || index >= getCount()) {
            return;
        }
        remove(getItem(index));
    }
}
```
#その他のクラス
　あとはもうひとつのタブに適当なフラグメントをSetします。それだけ。
　カスタムビューを一応作りました、適当ですね。

```custom_listview_item.xml
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_margin="8dp"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/id"
        android:layout_width="wrap_content"
        android:layout_height="48dp"
        android:layout_weight="1"
        android:background="@drawable/border"
        android:gravity="center"
        android:text="id"/>
    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="48dp"
        android:paddingLeft="16dp"
        android:layout_weight="4"
        android:background="@drawable/border"
        android:gravity="center_vertical"
        android:text="name"/>

</LinearLayout>
```

#実行確認
 私の実機(Sony SOL25)で動作を確認しました。
![Screenshot_2014-07-14-03-43-35.png](https://qiita-image-store.s3.amazonaws.com/0/48605/6f655ea5-55bd-f911-41c5-5e7348f868c3.png "Screenshot_2014-07-14-03-43-35.png")

#おわりに
 [Github](https://github.com/mackiso/MySamples)にてProjectを公開しております。割愛した説明はここを見てもらえれば。
 また、説明不足が際立つ(説明してない)。メモとして見返してこれでわかるか、いや、わかるまい。質問等あれば適宜、追記したいところ。なくても追記したいところ。

 ご指摘やアドバイス等を頂けると本当に幸いです。


#参考
[技術見聞録 - ListViewのカスタムビューを作るときにやるべきこと](http://www18.atwiki.jp/bovecrach/pages/27.html)
[Android　Parcelable を使ってクラスのメンバを一時保存](http://y-anz-m.blogspot.jp/2010/03/androidparcelable.html)
[美しいOnClickListenerの実装方法(を教えてください)](http://qiita.com/t2low/items/8ac683c7ebf4b6dd1b41)
[ListFragment | Android Developers](http://developer.android.com/reference/android/app/ListFragment.html)