AndroidのListViewには、iPhoneのUITableViewのsectionのような概念がありません。
これをAndroidのListViewで実現するためのコンポーネントを簡単に作って見ました。
public class MultiSectionAdapter extends BaseAdapter {
/** セルがセクションヘッダーであることを表す値 */
public final static int TYPE_SECTION_HEADER = 0;
/** 各セクションのValue部を保持するアダプターの集合 */
public final Map sections = new LinkedHashMap();
/** セクションヘッダーアダプター */
public final ArrayAdapter headers;
public final Context context;
public MultiSectionAdapter(Context context) {
super();
this.context = context;
headers = new ArrayAdapter(context, R.layout.list_section_header);
}
@Override
public int getCount() {
// ヘッダーを除いて、セルの数を返す
int total = 0;
for(Adapter adapter : this.sections.values()) {
if (adapter == null) {
continue;
}
total += adapter.getCount() + 1;
}
return total;
}
@Override
public Object getItem(int position) {
for(Object section : this.sections.keySet()) {
Adapter adapter = sections.get(section);
int size = adapter.getCount() + 1;
if(position == 0) return section;
if(position < size) return adapter.getItem(position - 1);
position -= size;
}
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getViewTypeCount() {
int total = 1;
for(Adapter adapter : this.sections.values()) {
if (adapter == null) {
continue;
}
total += adapter.getViewTypeCount();
}
return total;
}
@Override
public int getItemViewType(int position) {
int type = 1;
for(Object section : this.sections.keySet()) {
Adapter adapter = sections.get(section);
int size = adapter.getCount() + 1;
if(position == 0) return TYPE_SECTION_HEADER;
if(position < size) return type + adapter.getItemViewType(position - 1);
position -= size;
type += adapter.getViewTypeCount();
}
return -1;
}
@Override
public boolean isEnabled(int position) {
return (getItemViewType(position) != TYPE_SECTION_HEADER);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
int sectionNum = 0;
for(Object section : this.sections.keySet()) {
Adapter adapter = sections.get(section);
int size = adapter.getCount() + 1;
if(position == 0) return headers.getView(sectionNum, null, parent);
if(position < size) return adapter.getView(position - 1, convertView, parent);
position -= size;
sectionNum++;
}
return null;
}
/**
* セクションヘッダーと対となるアダプターをセットする
*
* @param section セクションヘッダー
* @param adapter セクションアダプター
*/
public void addSection(String section, Adapter adapter) {
this.headers.add(section);
this.sections.put(section, adapter);
}
}
そして色々と端折ってますが、このAdapterは以下のように利用します。
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ListView list = (ListView) findViewById(R.id.listView);
// MultiSectionAdapterに追加するセクション その1
@SuppressWarnings("serial")
List names1 = new ArrayList(){{add("相田"); add("石田"); add("上田");}};
ArrayAdapter adapter1 = new ArrayAdapter(this, android.R.layout.simple_list_item_1, names1);
// MultiSectionAdapterに追加するセクション その2
@SuppressWarnings("serial")
List names2 = new ArrayList(){{add("加藤"); add("木村"); add("久保");}};
ArrayAdapter adapter2 = new ArrayAdapter(this, android.R.layout.simple_list_item_1, names2);
// ヘッダー部のラベルと、対応するAdapterを渡す
UserAdapter adapter = new UserAdapter(this);
adapter.addSection("ア行", adapter1);
adapter.addSection("カ行", adapter2);
list.setAdapter(adapter);
}
}
class UserAdapter extends MultiSectionAdapter {
public UserAdapter(Context context) {
super(context);
}
}
- ヘッダー部に任意のViewを指定できない
- UITableViewと比較して、footer部がない
などなど、幾つかの不足・問題点はあるのですが、
現実の要件としてはこれで十分事足りるのではないかと思います。

0 件のコメント:
コメントを投稿