Fragmenty jsou nezbytným nástrojem při vývoji moderních uživatelských rozhraní v Android aplikacích. Umožňují rozdělit obrazovku na menší, nezávislé části, které lze snadno opakovaně použít. Zatímco v minulosti Android podporoval pouze aktivity, postupem času, zejména s příchodem tabletů, vznikla potřeba vytvářet flexibilní rozhraní, které by se přizpůsobovalo různým velikostem obrazovek a poskytovalo uživatelům lepší interakci. Fragmenty se staly klíčovým nástrojem pro tento účel.

Fragmenty fungují podobně jako mini-aktivity – mají vlastní třídy, rozvržení a životní cyklus. Místo vytváření monolitických rozhraní v jedné aktivitě lze obrazovku rozdělit na menší logické části, které jsou následně spravovány jako fragmenty. Tento přístup nabízí vyšší úroveň modularity, snadnou údržbu a možnost dynamické změny UI během běhu aplikace.

První tři příklady se zaměří na tvorbu a správu fragmentů. Další části kapitoly se pak budou věnovat širším možnostem přizpůsobení uživatelského rozhraní, jako je přidání widgetů na domovskou obrazovku nebo rozšíření funkčnosti pomocí systému UI.

Tvorba a použití fragmentu

Podpora pro fragmenty byla přidána až v Androidu 3.0, který přišel spolu s tablety. Předtím Android umožňoval pouze práci s aktivitami, které měly omezenou schopnost přizpůsobit se různým velikostem obrazovek. Fragmenty tedy představují způsob, jakým se Android začal adaptovat na tuto novou výzvu.

Každý fragment má svůj vlastní životní cyklus, který je podobný životnímu cyklu aktivit. To znamená, že každá fáze fragmentu – od jeho připojení k aktivitě až po jeho zničení – má své specifické metody, které je možné přetížit a přizpůsobit aplikaci. Mezi klíčové metody patří:

  • onAttach(): fragment je přiřazen k aktivitě.

  • onCreate(): fragment je vytvořen.

  • onCreateView(): fragment se připravuje k zobrazení.

  • onActivityCreated(): aktivita je plně vytvořena.

  • onStart(): fragment je připraven k zobrazení.

  • onResume(): fragment je zobrazen uživateli.

  • onPause(): fragment je pozastaven, je potřeba uložit uživatelská data.

  • onStop(): fragment není viditelný pro uživatele.

  • onDestroyView(): fragment se připravuje na zničení.

  • onDetach(): fragment je odpojen od aktivity.

Pro tento úvodní příklad vytvoříme základní fragment, který bude mít svůj layout a bude vložen do aktivity. Tento proces zahrnuje několik kroků – vytvoření souboru pro layout fragmentu a následné přidání fragmentu do aktivity. Pokud používáme AppCompatActivity, podporuje již fragmenty, takže není třeba používat starší třídu FragmentActivity.

Dynamické přidávání a odebírání fragmentů

V předchozím příkladu jsme se seznámili s "statickým" fragmentem, který je definován přímo v layoutu. Tento přístup však neumožňuje měnit fragmenty během běhu aplikace. Pro flexibilitu je nutné použít fragmenty dynamicky. To znamená, že fragmenty nebudou přímo součástí layoutu, ale budou přidávány, odstraněny nebo nahrazovány během běhu aplikace prostřednictvím třídy FragmentManager.

Při práci s dynamickými fragmenty využíváme FragmentTransaction, což je API, které umožňuje přidávat, odebírat nebo měnit fragmenty v průběhu běhu aplikace. Transakce se skládají z několika kroků: zahájení transakce, provedení jedné nebo více akcí (např. přidání nebo odstranění fragmentu) a nakonec potvrzení transakce.

Pokud vytváříme aplikaci, která bude používat různé fragmenty v závislosti na orientaci zařízení, můžeme v res/layout složce definovat různé verze layoutu pro portrétní a landscape režimy. Tento způsob přizpůsobení UI je zásadní pro zajištění plynulé uživatelské zkušenosti na různých typech zařízení.

Důležitost správného životního cyklu fragmentů

I když se fragmenty mohou zdát jako jednoduché stavební bloky pro UI, je kladeno velké důraz na správu jejich životního cyklu. Nesprávné zacházení s fragmenty během jejich přechodů mezi stavy může vést k nežádoucím efektům, jako je ztráta dat nebo zbytečné zatížení aplikace. Proto je důležité věnovat pozornost metodám jako onSaveInstanceState(), které umožňují fragmentu zachovat svůj stav během změny konfigurace, například při otočení obrazovky.

Příklady a rozšíření

Kromě základních fragmentů, jako je Fragment nebo ListFragment, Android nabízí i specializované fragmenty, například DialogFragment pro vytváření modálních oken nebo PreferenceFragment pro správu nastavení. Při vývoji aplikace se často používají kombinace těchto fragmentů k dosažení požadovaného rozhraní.

Dynamické přidávání a odebírání fragmentů je nezbytné při tvorbě flexibilních aplikací, které se přizpůsobují různým situacím a potřebám uživatele. Schopnost změnit uživatelské rozhraní během běhu aplikace je klíčová pro moderní Android aplikace, které musí fungovat plynule a efektivně na širokém spektru zařízení.

Jak správně vracet výsledky mezi aktivitami v Androidu

Pro vrácení výsledku z jedné aktivity do druhé v Androidu je klíčová metoda startActivityForResult(). Tento přístup umožňuje jedné aktivitě předat požadavek na data, která budou vrácena po provedení nějaké akce ve druhé aktivitě. Proces zahrnuje několik jednoduchých kroků, díky kterým lze efektivně získat požadované výsledky.

Prvním krokem je otevření souboru MainActivity.java a přidání konstanty, která bude použita k předání výsledku mezi aktivitami. Přidejte následující řádek do třídy:

java
public static final String REQUEST_RESULT = "REQUEST_RESULT";

Dalším krokem je úprava metody onClickSwitchActivity(), která bude nyní volat druhou aktivitu a očekávat vrácení výsledku. Změníte způsob, jakým je volán záměr (intent), aby se aktivita spustila s očekáváním výsledku. Kód bude vypadat takto:

java
public void onClickSwitchActivity(View view) { EditText editText = (EditText) findViewById(R.id.editTextData); String text = editText.getText().toString();
Intent intent = new Intent(this, SecondActivity.class);
intent.putExtra(Intent.EXTRA_TEXT, text); startActivityForResult(intent,
1); }

Tento kód spustí druhou aktivitu a zároveň předá text zadaný uživatelem. Dále je potřeba přidat metodu onActivityResult(), která přijme výsledek vrácený druhou aktivitou. Příklad takové metody vypadá následovně:

java
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { Toast.makeText(this, Integer.toString(data.getIntExtra(REQUEST_RESULT, 0)), Toast.LENGTH_LONG).show(); } }

Tato metoda zpracuje výsledek, pokud byla akce úspěšně dokončena. Pokud je výsledek pozitivní (RESULT_OK), zobrazí se uživateli hodnota vrácená druhou aktivitou prostřednictvím Toast zprávy.

Posledním krokem je úprava metody onClickClose() ve druhé aktivitě (SecondActivity.java), která vrátí výsledek zpět do první aktivity. Tato metoda bude vypadat takto:

java
public void onClickClose(View view) {
Intent returnIntent = new Intent();
returnIntent.putExtra(MainActivity.REQUEST_RESULT,
42); setResult(RESULT_OK, returnIntent); finish(); }

Tento kód zajistí, že po zavření druhé aktivity bude výsledkem předána hodnota 42 zpět do první aktivity.

Jak to funguje

Získání výsledků zpět mezi aktivitami je poměrně jednoduché. Hlavní funkcí je metoda startActivityForResult(), která značí, že očekáváme návrat dat. Poté je nastavena zpětná vazba v podobě metody onActivityResult(), která data přijme a zpracuje. Aby druhá aktivita mohla vrátit hodnotu, použije metodu setResult(). V tomto případě je vrácena pevně stanovená hodnota 42, což slouží pouze k demonstrování konceptu.

Je dobrým zvykem kontrolovat stav návratu pomocí hodnoty kódu výsledku, abyste se ujistili, že uživatel akci nezrušil. Tato hodnota je ve skutečnosti celočíselná, ale systém ji používá jako logickou hodnotu. Je třeba zkontrolovat hodnoty RESULT_OK nebo RESULT_CANCEL a podle toho pokračovat v kódu. I když v našem příkladu druhá aktivita nemá tlačítko pro zrušení akce, je důležité mít na paměti, že pokud uživatel stiskne tlačítko zpět, systém nastaví kód výsledku na RESULT_CANCEL, což by mohlo vést k výjimce, pokud se kód nebude na tento stav připravit.

Další poznatky

Kromě samotného kódu výsledku obsahuje metoda onActivityResult() také hodnotu "Request Code". Ta identifikuje, z jaké aktivity pochází požadavek. Tento kód je předán při volání startActivityForResult(), což může být užitečné v případě aplikací s několika aktivitami. Pokud je startActivityForResult() volán s negativním číslem jako kód požadavku, systém se chová, jako by bylo volání realizováno pomocí startActivity(), tedy bez návratu výsledku.

V praxi se toto může využít k rozlišení různých aktivit, které vrací výsledky do jedné hlavní aktivity, což pomáhá udržovat kód přehledný.

Ukládání stavu aktivity

V mobilním prostředí je běžné, že aplikace jsou přerušeny nebo zcela uzavřeny, aby se uvolnily prostředky pro jiné úkoly. Pokud uživatel přepne na jinou aplikaci, může se stát, že systém uzavře vaši aplikaci, aby uvolnil paměť. To znamená, že jakákoli data, která byla zadána do aplikace, mohou být ztracena. Android OS však poskytuje mechanizmus pro zachování stavu aplikace, což umožňuje snadno obnovit uživatelský zážitek.

Pomocí metod onSaveInstanceState() a onRestoreInstanceState() můžeme uložit a obnovit stav aplikace při změně orientace zařízení nebo při jeho znovuotevření. Příklad ukazuje, jak lze uložit hodnotu čítače a obnovit ji po restartu aktivity.

Například:

java
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); outState.putInt(KEY_COUNTER, mCounter); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); mCounter = savedInstanceState.getInt(KEY_COUNTER); }

V tomto příkladu se hodnota čítače ukládá před zničením aktivity a obnoví se po jejím opětovném vytvoření. Tato schopnost zachovat stav aplikace je klíčová pro poskytování konzistentního uživatelského zážitku.