google-code-prettify

ラベル Adapter の投稿を表示しています。 すべての投稿を表示
ラベル Adapter の投稿を表示しています。 すべての投稿を表示

2013-04-15

Spinnerでは、AdapterのgetItemViewType()とgetViewTypeCount()が使えない

ListViewでは、AdapterのgetItemViewType()とgetViewTypeCount()をoverrideすることで、行ごとに違うViewを使うことができる。
しかし、SpinnerではgetItemViewType()とgetViewTypeCount()が呼ばれなく、行ごとに違うViewにするにはListViewとは異なる方法を取る必要がある。

Spinnerのprivateな内部クラスであるDropDownAdapterがAdapterをラップしているのだが、このラッパーは以下のように固定値を返すように実装されていて、setAdapter()でセットしたAdapterのgetItemViewType()とgetViewTypeCount()を呼んでくれない。
        public int getItemViewType(int position) {
            return 0;
        }

        public int getViewTypeCount() {
            return 1;
        }
Spinnerで行ごとに違うViewを使うには、以下のようにすると良い。
  • Viewの中に複数のViewを含めておいて、見せたいViewのVisibilityだけvisibleにし、その他をgoneにする。
  • getView()でconvertViewを再利用するのをやめて、毎回Viewをinflateする。もしくは、convertViewで渡されるViewのタイプを見て、再利用するかどうかを自分で決める。
参考: https://code.google.com/p/android/issues/detail?id=17128

ListViewで、行ごとに違うViewを使う

ListViewでAdapterを使う際、getItemViewType()とgetViewTypeCount()をoverrideすることで、ListView中に複数のViewを混ぜることができる。
例えば、3種類のviewが存在する場合、
int getItemViewType(int position) {
    return position % 3; // 行じ応じたViewのタイプを返す。タイプは0,1,2,3...と0始まりであること。
}

int getViewTypeCount() {
    return 3; // Viewのタイプの数
}
としておく。
View getView(int position, View convertView, ViewGroup parent)
に渡されてくるconvertViewには再利用されるべきViewが渡されてくるのだが、上記のようにgetItemViewType()とgetViewTypeCount()をoverrideしていれば、そのpositionに応じた正しい種類のViewがconvertViewに渡されてくる。

コード例:
int getItemViewType(int position) {
    return position % 3; // 行じ応じたViewのタイプを返す。タイプは0,1,2,3...と0始まりであること。
}

int getViewTypeCount() {
    return 3; // Viewのタイプの数
}

View getView(int position, View convertView, ViewGroup parent) {
    switch (getItemViewType(position)) {
    case 0:
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.item1, parent, false);
        }
        break;
    case 1:
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.item2, parent, false);
        }
        break;
    case 2:
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.item3, parent, false);
        }
        break;
    }
    return convertView;
}