ListView を用いて、ListView の中に GridView をねじ込んで実装する。
+--------------------+
| Header content |
+------+------+------+
| Cell | Cell | Cell |
+------+------+------+
| Cell | Cell | Cell |
+------+------+------+
| Cell | Cell | Cell |
+------+------+------+
| Header content |
+------+------+------+
| Cell | Cell | Cell |
+------+------+------+
| Cell | Cell | Cell |
+------+------+------+
| Cell | Cell | Cell |
+------+------+------+
...
データ構造
一行分のデータを表すデータ構造は、
- セクションヘッダーとして取り扱う為のデータ
- GridView に表示するリストのデータ
このデータ構造を保持するコレクションを作って、ListView のアダプターに渡していくスタイル。
public class SectionData {
private String mSectionName;
private List<String> mImages;
}
レイアウト
リストの一行ごとに、GridView をねじ込んでいくスタイル。こうすれば、一行ごとのレイアウトに、GridView のセクションヘッダーの役割を果たすレイアウトを含めることが出来る。
このとき、スクロールのハンドリングが ListView と GridView で二重化してしまうので、GridView のスクロールをしないよう、高さを中身の数に合わせて固定化する(参考リンク)。
// StackOverFlow の回答の実装
public class NonScrollableGridView extends GridView {
public NonScrollableGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Do not use the highest two bits of Integer.MAX_VALUE because they are
// reserved for the MeasureSpec mode
int heightSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightSpec);
getLayoutParams().height = getMeasuredHeight();
}
}
アダプター
ListView 用のアダプターと、GridView 用のアダプターを用意する。
ListView 用のアダプターの ListAdapter#getView(int, View, ViewGroup)
では、GridView の初期化と GridView 用のアダプターの初期化および設定をする。
public class SectionListAdapter extends ArrayAdapter<SectionData> {
public SectionListAdapter(Context context, List<SectionData> objects) {
super(context, R.layout.list_item_layout, R.id.label_section_title, objects);
}
@Nullable
@Override
public View getView(int position, View convertView, ViewGroup group) {
View row = super.getView(position, convertView, group);
SectionData data = getItem(position);
TextView sectionName = (TextView) row.findViewById(R.id.label_section_name);
sectionName.setText(data.getSectionName());
GridView grid = (GridView) row.findViewById(R.id.grid);
SectionGridAdapter adapter = new SectionGridAdapter(getContext(), data.getImageUrls());
grid.setAdapter(adapter);
return row;
}
}
GridView 用のアダプターは、いつもどおりセルのレイアウトを生成するコードを書く。
public class SectionGridAdapter extends ArrayAdapter<String> {
public SectionGridAdapter(Context context, List<String> objects) {
super(context, R.layout.grid_item, R.id.label_grid, objects);
}
@Nullable
@Override
public View getView(int position, View convertView, ViewGroup group) {
View cell = super.getView(position, convertView, group);
ImageView image = (ImageView) cell.findViewById(R.id.image_cell);
// Picasso 使うなら
Picasso.with(getContext()).load(getItem(position)).into(image);
return cell;
}
}
もっと読むとか PullToRefresh とか
ListView なので、もっと読むは FooterView が使える。
PullToRefresh も、このライブラリであれば、ListView を PullToRefreshListView に置き換えて使うことができる。
簡単!