Lišta akcií v Androide 4.x významne zmenila pohľad na používateľské rozhranie. Nielenže zahŕňa tlačidlá pre význačné akcie a kebabové menu pre sekundárne činnosti v aktivite, ale môže obsahovať aktívnu ikonku... a v prípade potreby i karty tabs.
Ako hovorí dizajnový manuál, karty slúžia na prepínanie medzi rozličnými pohľadmi na údaje v aktivite alebo na prehliadanie kategórií dát.
Pekným príkladom je kategorizácia aplikácií v Google Play Store, kde vidno dve karty: pre aplikácie nainštalované na aktuálnom zariadení a pre všetky zakúpené aplikácie.
Ukážme si aplikáciu, na ktorej predvedieme použitie kariet!
Vytvoríme si aplikáciu, ktorá bude zobrazovať zoznamy krajov a okresov Slovenska. Na jednotlivé kategórie použijeme karty.

Založme si teda aplikáciu Slovensko s jedinou aktivitou.
Štruktúra aplikácie bude nasledovná:
Vytvorme v projekte triedu RegionFragment dediaci od ListFragment. Tento
predlohový fragment v sebe definuje layout pre zoznam.
Dodajme do reťazcového resource súboru strings.xml pole s názvami krajov:
<string-array name="regionNames">
<item>Bratislavský</item>
<item>Trnavský</item>
<item>Trenčiansky</item>
<item>Nitriansky</item>
<item>Žilinský</item>
<item>Banskobystrický</item>
<item>Prešovský</item>
<item>Košický</item>
</string-array>
Kód aktivity potom bude pozostávať z vytvorenia adaptéra pre položky zoznamu a jeho prepojenia s fragmentom:
public class RegionListFragment extends android.support.v4.app.ListFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setListAdapter(ArrayAdapter.createFromResource(getActivity(), R.array.regionNames, android.R.layout.simple_list_item_1));
return super.onCreateView(inflater, container, savedInstanceState);
}
}
Všimnime si, ako sme využili statickú metódu createFromResource(), ktorá vie vytvoriť adaptér
na základe prvkov v poli string-array v resource súbore.
V aplikácii budeme využívať knižnicu kompatibility, preto i fragmenty, i neskoršie
použitá lišta akcií bude z balíčka v4, resp. v7.
Proces zopakujeme ešte raz: vytvoríme pole reťazcov s názvami okresov:
<string-array name="countyNames">
<item>Bánovce nad Bebravou</item>
<item>Banská Bystrica</item>
<item>Žilina</item>
...
</string-array>
Fragment pre okresy bude takmer identický s krajovou verziou, až na referenciu na resource s položkami:
public class CountyListFragment extends android.support.v4.app.ListFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setListAdapter(ArrayAdapter.createFromResource(getActivity(), R.array.countyNames, android.R.layout.simple_list_item_1));
return super.onCreateView(inflater, container, savedInstanceState);
}
}
Ako pridáme novú kartu do lišty akcií? Lišta akcií, ktorú možno v aktivite
získať volaním getActionBar() na aktivite, poskytuje továrenskú metódu
newTab(), ktorou vytvoríme inštanciu objektu pre kartu typu ActionBar.Tab.
private void configureRegionListTab() {
ActionBar actionBar = getSupportActionBar();
ActionBar.Tab tab = actionBar.newTab();
tab.setText("Kraje");
tab.setTabListener(this);
tab.setTag(RegionListFragment.class.getName());
actionBar.addTab(tab);
}
Tento objekt má povinne nastaviteľný textový popisok a poslucháča, ktorý bude zodpovedný za správu obsahu aktivity pri klikaní na hlavičky kariet.
Poslucháč zmien je typu ActionBar.TabListener, a povieme si o ňom neskôr.
Posledný nastaveným atribútom je tag, čo je ľubovoľný objekt asociovaný s kartou.
V našom prípade si do tagu poznačíme názov triedy fragmentu, ktorý reprezentuje
obsah karty. Tento tag totiž využijeme neskôr pri dynamickom zobrazovaní a skrývaní
kariet.
Ak používateľ kliká na hlavičky kariet, je potrebné vymieňať obsah aktivity. A ako sa najlepšie vymieňajú obsahy? Pomocou manipulácie s fragmentami! Fragment je totiž, ako vraví definícia, znovupoužiteľný panel s komponentami a práve fragmenty budú obsahovať „telá“ jednotlivých kariet.
Na sledovanie zmien výberu kariet slúži poslucháč ActionBar.TabListener s troma metódami:
onTabSelected() sa zavolá pri zvolení a zobrazovaní novej karty. Tu sa tradične vytvára alebo obnovuje fragment a následne sa zobrazí.onTabUnselected() sa zavolá pri skrývaní karty, ktorá bude nahradená inou vybranou kartou, čiže volá sa pri zrušení výberu karty. Tu potrebujeme odpojiť existujúci fragment od aktuálneho komponentuonTabReselected() ak sa nanovo vyberie nová karta. V tejto metóde sa tradične nedeje nič.V aktivite musíme ešte zapnúť zobrazovanie kariet na lište akcií: nastavme teda
režim navigácie na NAVIGATION_MODE_TABS.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
configureRegionListTab();
configureCountyListTab();
}
Kód aktivity bude vyzerať nasledovne:
public class MainActivity extends AppCompatActivity implements ActionBar.TabListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
configureRegionListTab();
}
private void configureRegionListTab() {
ActionBar.Tab tab = getSupportActionBar().newTab();
tab.setText("Kraje");
tab.setTabListener(this);
tab.setTag(RegionListFragment.class.getName());
getActionBar().addTab(tab);
}
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
}
Metóda poskytuje dva parametre: tab reprezentujúci objekt karty, ktorá sa mieni zobraziť a
transakcia FragmentTransaction v rámci ktorej prebehne výmena obsahov (fragmentov) kariet.
Ako zistíme, ktorý fragment sa má zobraziť? Využijeme názov triedy fragmentu,
ktorý sme si uložili do tagu pri vytváraní karty Tab.
Z karty tab teda vytiahneme tag obsahujúci názov triedy fragmentu, ktorá sa má
použiť. Následne môžu nastať dva prípady:
Fragment.instantiate(),
ktorá vezme názov triedy fragmentu a vráti jej inštanciu. Výsledok pridáme do
transakie cez metódu add(), čím pridáme fragment do aktivity. Pridávanie do
transakcie zároveň využije reťazcový tag, ktorým budeme určovať v druhom prípade,
či už bol fragment vytvorený alebo nie. Dôležitý je i layout, do ktorého
sa pridáva fragment: využijeme koreňový layout aktivity, ktorý je reprezentovaný
systémovým identifikátorom android.R.id.content.Ak je popis tiahly, kód ho sprehľadní:
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
String tag = (String) tab.getTag();
String fragmentClassName = tag;
Fragment selectedFragment = getSupportFragmentManager().findFragmentByTag(tag);
if (selectedFragment == null) {
selectedFragment = Fragment.instantiate(this, fragmentClassName);
ft.add(android.R.id.content, selectedFragment, tag);
} else {
ft.attach(selectedFragment);
}
}
Ak sa skrýva karta, ktorá už nie je potrebná, zavolá sa metóda
onTabUnselected():
V tomto prípade získame tag z aktuálne vybranej karty, pohľadáme k nemu priradený fragment v správcovi fragmentov a ak ho nájdeme, odpojíme ho od aktivity.
@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
String tag = (String) tab.getTag();
Fragment selectedFragment = getSupportFragmentManager().findFragmentByTag(tag);
if (selectedFragment != null) {
ft.detach(selectedFragment);
}
}
Tag v tomto prípade reprezentuje dve veci: tag súvisiaci s kartou a tag súvisiaci s identifikátorom fragmentu v transakcii. Oba tagy sú reprezentované názvom triedy fragmentu. Potom sa použije na:
Transakcia v parametri FragmentTransaction sa nesmie komitnúť v kóde! Urobí
to za vás správca kariet. (V opačnom prípade hrozí výnimka).
Okrem toho je zakázané uložiť transakciu na zásobník fragmentov back stack.
V prípade nového výberu karty sa nestane nič: obvykle sa telo metódy necháva prázdne.
Dodajme do aktivity i druhú kartu, kde kód pre vytváranie bude veľmi podobný karte krajov.
private void configureCountyListTab() {
ActionBar actionBar = getSupportActionBar();
ActionBar.Tab tab = actionBar.newTab();
tab.setText("Okresy");
tab.setTabListener(this);
tab.setTag(CountyListFragment.class.getName());
actionBar.addTab(tab);
}
Aplikácia je funkčná a môžeme ju spustiť! Máme možnosť prepínať sa medzi dvoma kartami, kde sa pod každou schováva jeden fragment.
Karty sú veľmi užitočný navigačný prvok. Ak je ich primnoho, je možno lepšie použiť výsuvný navigačný panel (navigation drawer). Druhou možnosťou je skombinovať ich s horizontálnym stránkovačom (page drawer), kde ukážu používateľovi aktuálnu polohu pri prehliadaní kolekcie prvkov.