12 Abr, 2012 20:30
Criando lista com seções em Android - Revisitado
Os métodos são:
// número de seções da lista
abstract protected int getSectionCount();
// número de itens de uma dada seção
abstract protected int getItemCountForSection(int sectionIndex);
// objeto associado a um dado item de uma dada seção
abstract protected Object getItemForSection(int sectionIndex, int itemIndex);
// id de um dado item de uma dada seção
abstract protected long getItemIdForSection(int sectionIndex, int itemIndex);
// view associada a uma dada seção
abstract protected View getSectionView(int sectionIndex, View convertView, ViewGroup parent);
// view associado a um dado item de uma dada seção
abstract protected View getSectionItemView(int sectionIndex, int itemIndex, View convertView, ViewGroup parent);
Esses métodos permitem ao programador utilizar uma estrutura de dados totalmente coerente com a apresentação, i.e. um array de objetos tipo "Seção" que, por sua vez, possuem um array de objetos tipo "Item". Com isso, uma implementação de uma subclasse do nosso adapter poderia ser:
ArrayList<Secao> secoes;
@Override
protected int getSectionCount() {
return secoes.size;
}
@Override
protected int getItemCountForSection(int sectionIndex) {
return secoes.get(sectionIndex).getItems().size
}
@Override
protected Object getItemForSection(int sectionIndex, int itemIndex) {
return secoes.get(sectionIndex).getItems().get(itemIndex);
}
@Override
protected long getItemIdForSection(int sectionIndex, int itemIndex) {
return secoes.get(sectionIndex).getItems().get(itemIndex).getId();
}
@Override
protected View getSectionView(int section, View convertView, ViewGroup parent) {
TextView view = (TextView) convertView;
if (view == null)
view = (TextView) inflater.inflate(R.layout.section_item, null);
view.setText(secoes.get(section).getNome());
return view;
}
@Override
protected View getSectionItemView(int section, int item, View convertView, ViewGroup parent) {
TextView view = (TextView) convertView;
if (view == null)
view = (TextView) inflater.inflate(R.layout.list_item, null);
view.setText(secoes.get(sectionIndex).getItems().get(itemIndex).getNome());
return view;
}
E o resultado seria:
Muito simples, não?
E o tratamento de eventos na lista? O SectionAdapter serve de fachada entre os métodos comuns de ListAdapter e os métodos especiais que apresentei acima. Sendo assim, é possível tratar o SectionAdapter como um adapter normal na hora de tratar os eventos. Ex:
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
//SectionAdapter responde corretamente a getItem e getItemId sem necessidade de qualquer implementação extra
Item item = (Item)sectionAdapter.getItem(position);
Intent intent = new Intent(getApplicationContext(), LojaActivity.class);
intent.putExtra("item", item);
startActivity(intent);
}
Limitação: atualmente, o SectionAdapter divide os tipos de view em dois (section e item), o que define o comportamento do reaproveitamento das views no getView. Caso haja a necessidade de haver mais de um tipo de view para seções ou itens, será necessário mexer diretamente na implentação de SectionAdapter. Se um dia eu fizer essa mudança, volto aqui e compartilho com vocês. ;)
Você pode baixar o código-fonte necessário para usar o SectionAdapter aqui. Qualquer sugestão será bem vinda.