Если вы хотите избежать создания подкласса BaseAdapter, но хотите работать с настраиваемыми представлениями элементов и настраиваемой логикой щелчков элементов на основе объекта, вот что я сделал.
В моем коде я работаю с коллекцией некоторого объекта модели. Я хочу отобразить эту коллекцию объектов модели в ListView. Я не могу просто передать ArrayList ModelObjects в SimpleAdapter, потому что он ожидает список пар ключ-значение (что-то вроде List<Map<String, Object>>
). Таким образом, вместо того, чтобы использовать простую коллекцию моего объекта в моем приложении, я создал собственный класс для представления своей коллекции, который просто происходит от структуры, которую я использовал. Таким образом, я могу продолжать использовать его, как и раньше, но я могу добавить метод, который преобразует его из коллекции, удобной для кода, в коллекцию, удобную для SimpleAdapter. В моем случае я использовал HashMap с ключом некоторого строкового свойства (т.е. HashMap<String, ModelObject>
). Мой пользовательский класс коллекции будет ModelObjects
(множественное число) extends HashMap<String, ModelObject>
. ModelObjects
будет содержать метод ToList()
, в котором я преобразую свои объекты в ArrayList<? extends HashMap<String, ?>>
, который затем я могу передать конструктору SimpleAdapter, чтобы отобразить его в списке с настраиваемым представлением.
Так что теперь я могу создать SimpleAdapter со следующими пятью параметрами:
- Контекст моего списка (в моем случае, содержащая активность)
- Мой список (описан выше)
- Идентификатор моего пользовательского макета для этих элементов (R.layout.custom_list_item)
- Строковый массив имен свойств. Это ключи в HashMap из моего метода ToList.
- Массив int, который отображает свойства каждого элемента выше (# 4) на идентификатор элемента, производный от View, в моей пользовательской компоновке
Затем в моем методе OnItemClickListener.onItemClick я могу использовать arg3, чтобы получить позицию элемента в моем списке, по которой был выполнен щелчок, и использовать его, чтобы выбрать объект из моей коллекции. Вы можете воздействовать на любые свойства вашего элемента или сделать большой переход / случай для какого-либо свойства вашего объекта, чтобы запустить определенное действие или что-то в этом роде.
Единственная хитрость в том, что вам нужно хранить локальную копию вашей коллекции в рамках действия, которое не изменяется. В противном случае вы можете искать объект по идентификатору в onItemClick и получать объект, отличный от ожидаемого. Это может быть немного вне контекста, но вот как выглядит мой код:
ListView lvArtists = (ListView)findViewById(R.id.lvArtists);
SimpleAdapter adapter = new SimpleAdapter(
this,
artists.ToList(),
R.layout.artist_list_item,
new String[] { "name", "imageIdSmall", "tracksCount", "tracksPending" },
new int[] { R.id.artistListItemName, R.id.artistListItemImage, R.id.artistListItemAudioClips, R.id.artistListItemAudioClipsPending }
);
lvArtists.setAdapter(adapter);
lvArtists.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
Artist artist = artists.getSortedItem((int)arg3);
mArtistDialog.setArtist(artist);
mArtistDialog.show();
}
});