11
Kontextové menu se velmi často používá v případě, kdy máme seznam určitých položek načten v seznamu (ListView
, GridView
,…) a chceme přiřadit každé položce z tohoto seznamu kontextové menu. Nejlépe si tuto možnost vysvětlíme na jednoduchém příkladu.
Přidejme k přehledu záznamů v aplikaci, kterou jsme naprogramovali v předchozích kapitolách. Do kontextového menu pro jednotlivé položky přidáme volby „Odstranit“, „Přepni důležitost“ a „Upravit“. Položky „Odstranit“ a „Přepni důležitost“ implementujeme, volbu „Upravit“ realizujeme až v příští kapitole, kde se zároveň naučíme vytvářet a volat nové aktivity (další obrazovky aplikace).
Celá aplikace bude ve výsledku vypadat takto:
Obrázek 1 –
Postup:
ListView
, která bere položky z kontejneru ArrayList
.)
Zaznam
s textovými atributy nazev
a popis
a atributem dulezite
, který je datového typu logická hodnota (boolean
).
Pro snazší práci a pro dodržení principu zapouzdření si do třídy Data
přidáme metody:
public Zaznam getZaznam(int pozice) { return this.data.get(pozice); } public void odstranZaznam(int pozice) { this.data.remove(pozice); this.notifyObservers(); }
<string name="app_name">Můj pestrý život</string> <string name="menu_load_file">Obnov</string> <string name="menu_save_file">Ulož</string> <string name="kmenu_remove">Odeber záznam</string> <string name="kmenu_change_importance">Přepni důležitost</string> <string name="kmenu_edit">Uprav záznam...</string> </resources>
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/km_remove" android:title="@string/kmenu_remove" android:orderInCategory="100" app:showAsAction="never" /> <item android:id="@+id/km_change_importance" android:title="@string/kmenu_change_importance" android:orderInCategory="100" app:showAsAction="never" /> <item android:id="@+id/km_edit" android:title="@string/kmenu_edit" android:orderInCategory="100" app:showAsAction="never" /> </menu>
ListView
) nyní zaregistrujemev metodě onCreate(…)
hlavní aktivity kontextové menu – tím řekneme překladači, že chceme, aby položky ListView měly kontextové menu. To jsme se již naučili v předchozí kapitole:
this.registerForContextMenu(this.seznam);
@Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.kontext_menu_zaznamy, menu); }
Aplikaci můžeme nyní zkusit spustit. Kontextové menu je u každé položky (záznamu), zatím ale nereaguje na výběr.
Reakce na volbu položky z menu:
onContextItemSelected(…)
pro reakci na výběr položky. Pro určení, na jakou položku v ListView
jsme klikli, využijeme třídu AdapterContextMenuInfo
.
V případě potřeby o změně dat v ArrayListu
informujeme adaptér metodou notifyDataSetChanged()
– to už známe z kapitoly o ListView
. Naše třídy již mají informaci o změně vyřešenu pomocí mechanismu pozorovatele.@Override public boolean onContextItemSelected(MenuItem item) { AdapterView.AdapterContextMenuInfo infoOZvolenePolozce = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); switch(item.getItemId()) { case R.id.km_change_importance: Zaznam zaznam = this.zaznamy.getZaznam(infoOZvolenePolozce.position); zaznam.invertujDulezite(); return true; case R.id.km_edit: Toast.makeText(this, "Editace zatím není implementována", Toast.LENGTH_SHORT).show(); return true; case R.id.km_remove: this.zaznamy.odstranZaznam(infoOZvolenePolozce.position); default: return super.onContextItemSelected(item); } }
ListView
,…) registrujeme kontextové menu pro celý seznam.
MenuItem.getItemId()
sdělí ID zvolené položky menu.AdapterView.AdapterContextMenuInfo
.
Tato třída nese atribut position
, který udává pozici zvolené položky v adaptéru.
Instanci třídy získáme metodou MenuItem.getMenuInfo()
.