Népszerű és mindenképp használatra javasolt komponens Androidon a ListView. Gyakorlatilag a legtöbbet használt UI elem, bárhmely programot használunk, rendszeresen feltűnik különböző formákban. Lényege, hogy a képernyőn megjelenő elemeket egy listába rendezzük, és ezt a listát görgethetjük le-fel ha nem fér ki minden elem a képernyőre. Használata relative egyszerű, amíg nem akarunk egyedi megjelenést, például Button vagyCheckbox komponenseket belerakni, mert ekkor azonnal beleütközünk a problémába, a ListView onItemClickevent handler nem hívódik meg kattintáskor.
Az Internet tele van a problémával, de teljes egészében leírt megoldást ritkán találni. Általában utalások vannak rá, hogy tároljunk ID-t a Tag mezőben, vagy írjuk át az Adapter-t, de mik is ezek az utalások tulajdonképpen?
A feladat amit kitaláltam egy olyan ListView megjelenítés, ami a SimpleAdaptert-t használja adatforrásnak, így a layout betölthető XML-ből egyszrűen. A layout tartalmaz egy gombot, amit megnyomva az Activity onClick metódusa hívódik meg. A probléma itt következik: az onClick az onItemClick-el ellentétben nem kapja meg melyik soron kattintottunk. Valahonnan pedig illene tudni, hiszen nem minden soron ugyanazt szeretnénk végrehajtani.
Az ötelt a fent amlített netes leírások alapján adja magát, tároljuk le az onClick-et meghívó View Tag-jében (View.setTag(Object o)) a szükséges azonosítót, így az onClick-ben a paraméterként megkapott View-tól le tudjuk kérdezni.
Minden ListView a lista elemeit egy Adapter osztálytól kapja (ListView.setAdapter()) a getView() metóduson keresztül. Az adapter kis átírásával megoldható, hogy a lista elemeibe bekerüljön a az Id a megfelelő Tag property-be, amikor a ListView meghívja a getView()-t. Leszármaztattam hát a SimpleAdaptert-t:
public class ClickableButtonListAdapter extends SimpleAdapter {
private static final String HASHMAP_ID = "_id";
public ClickableButtonListAdapter(Context context,
List<? extends Map<String, ?>> data, int resource, String[] from,
int[] to) {
super(context, data, resource, from, to);
}
@SuppressWarnings("unchecked")
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
setViewTag(view, ((HashMap<String,String>) getItem(position)).get(HASHMAP_ID) );
return view;
}
private void setViewTag(View view, Object tag) {
view.setTag(tag);
if (view instanceof ViewGroup) {
for (int i=0; i < ((ViewGroup) view).getChildCount(); i++) {
setViewTag(((ViewGroup) view).getChildAt(i), tag);
}
}
}
}
A példában a lista elemei HashMap-ek, így ebből szedem ki az Id-t. A HahMap-ben az Id mező az “_id” elemben van, így ezt keresem ki, és rakom a Tag-be. A setViewTag() rekurzív metódus végigmegy az összes megjelenítendő View elemen és beállítja a Tag-et, így bármelyikre definiálhatjuk majd az onClick-et, mindig megkapjuk a Tag-ben a kiválasztott sor Id-ját.
Az Activity-ben az onClick() igen egyszerű:
public void onClick(View v) {
Toast.makeText(this, "onClick id: " + v.getTag(), Toast.LENGTH_SHORT).show();
}
Nem mondom, hogy szép megoldás, de használható. Jobban tetszene, ha az Android megfelelően támogatná az egyedi ListView létrehozását esetleg azzal, hogy az onItemClick meghívódna, és eldönthetném, hogy mit akarok kezdeni az eseménnyel.
Címkék: android, fejlesztés, java, Mobil