Image
14.1.2015 0 Comments

Fragmenty – spoločná aplikácia pre telefón aj tablet

S príchodom tabletov sa začala pre vývojárov dilema. Keby ste aplikáciu určenú pre telefóny spustili na veľkom displeji tabletu, väčšina obrazovky by bola nevyužitá. Opačne, keby sme aplikáciu navrhli primárne pre tablet, na menších displejoch telefónov by používateľské rozhranie aplikácie bolo nečitateľné, prípadne by sa vôbec nedalo zobraziť. Jedno z najefektívnejších riešení sú fragmenty dostupné od verzie Android 3.0.

Fragmenty sú hostované v aktivitách. Jedna aktivita môže hostovať jeden alebo viac fragmentov. Životný cyklus fragmentu sa viaže na životný cyklus aktivity, v ktorej je hostovaný, a je s ním koordinovaný. Typický scenár pre fragmenty je zobrazenie informácie typu master - detail. Zoznam objektov sa vypíše v jednom fragmente a detailné informácie o objektoch v druhom. Na zariadeniach s malým displejom sa zobrazí každý fragment v samostatnej aktivite. Na tabletoch s veľkým displejom sa zobrazia obidva fragmenty v rámci jednej aktivity vedľa seba.

Námet príkladu

Vytváranie a fungovanie fragmentov vysvetlíme najlepšie na praktickom príklade. Jeho námetom bude aplikácia so zoznamom slovenských zastupiteľstiev v zahraničí. O zastupiteľstve vybranom používateľom treba vypísať podrobnejšie údaje.

Na telefóne s relatívne malým displejom sa na celej ploche displeja zobrazí ako hlavná aktivita aplikácie zoznam objektov, v tomto prípade krajín. Po kliknutí na niektorý objekt sa na ploche obrazovky zobrazí iná aktivita s detailnými informáciami o vybranom objekte. Aplikácia by v takejto podobe fungovala aj na tablete, no plocha v pravej časti displeja by zostávala nevyužitá.

fragmenty1.png

Zobrazenie zoznamu objektov (vľavo) a po výbere objektu zobrazenie podrobností na novej obrazovke (vpravo)

fragmenty2.png

Súčasné zobrazenie zoznamu objektov aj detailov o vybranom objekte na veľkom displeji tabletu

Projekt kompatibilný so staršími verziami

Aby sme demonštrovali kompatibilitu fragmentov aj na starších verziách, nastavte minimálnu verziu SDK na API 8 (Android 2.2 - Froyo). Keby ste ako minimálnu verziu SDK nastavili API 11 (Android 3.0), mohli by ste vytvoriť hlavnú aktivitu typu Master-Detail. V tomto príklade vytvorte hlavnú aktivitu typu Empty Activity. Hlavnú aktivitu vhodne pomenujte, napríklad ZoznamZastupitelstiev.

Aby ste mohli využívať podpornú knižnicu android.support.v4.app, sprístupňujúcu fragmenty aj pre prístroje s verziou Androidu nižšou než 3.0, musíte mať nainštalovaný komponent Android Support Library. Cez Android SDK Manager skontrolujte, či máte podpornú knižnicu nainštalovanú, ak nie, doinštalujte ju.

fragmenty3.png

Android Support Library v Android SDK Manager

Používateľské rozhranie aktivity na zobrazenie detailov pozostáva pre jednoduchosť z jediného prvku typu TextView v kontajneri LinearLayout. Keďže informácie o objekte môžu presiahnuť rozmery obrazovky, návrh aktivity obsahuje aj prvok ScrollView umožňujúci zvislé rolovanie.

detail.xml

android:layout_width="match_parent"

android:layout_height="wrap_content" >

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="vertical" >

android:id="@+id/detaily"

android:layout_width="match_parent"

android:layout_height="wrap_content"/>

Zobrazenie detailných informácií

Trieda DetailFragment na zobrazenie detailných informácií o vybranom objekte je odvodená od triedy Fragment. Každá takto odvodená trieda musí navyše prepisovať metódu onCreateView().

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,

Bundle savedInstanceState) {}

Parameter, v tomto prípade index aktuálne vybranej položky, sa na rozdiel od aktivít neodovzdáva pomocou intentov, ale priamo pomocou argumentov cez objekt typu Bundle.

public static DetailFragment newInstance(int index)

{

DetailFragment f = new DetailFragment();

Bundle argumenty = new Bundle();

argumenty.putInt(VYBER, index);

f.setArguments(argumenty);

return f;

}

Kompletný zdrojový kód fragmentu zobrazujúceho detailné informácie o zastupiteľstve vo vybranej krajine je v súbore DetailFragment.java.

public class DetailFragment extends Fragment

{

public static final String VYBER = "vyber";

protected static String[] informacie = new String[]

{

"Albánsko.\n"

+ "Veľvyslanectvo Slovenskej republiky v Tirane\n"

+ "Rruga Skenderbeu 8, Tirana, Albánsko.\n "

+ "TEL: 0035542274917 ",

"Info o Belgicku",

"Info o Bielorusku"

};

public static DetailFragment newInstance(int index)

{

DetailFragment f = new DetailFragment();

Bundle argumenty = new Bundle();

argumenty.putInt(VYBER, index);

f.setArguments(argumenty);

return f;

}

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,

Bundle savedInstanceState)

{

View vw = inflater.inflate(R.layout.detail, container, false);

int index = getArguments().getInt(VYBER, 0);

TextView tv = (TextView) vw.findViewById(R.id.detaily);

tv.setText(informacie[index]);

return vw;

}

}

Zobrazenie zoznamu objektov

Kód fragmentu obsahuje priamo statické údaje, v tomto prípade len niekoľko položiek. Zoznam sa naplní v metóde onActivityCreated cez objekt typu Context. V reálnej aplikácii by sa údaje načítali z webu napríklad cez JSON, z lokálnej databázy a podobne. Kľúčové dejstvo fragmentu nastane v okamihu výberu niektorej položky. V závislosti od veľkosti displeja, prípadne iných kritérií, napríklad orientácie zariadenia, treba rozhodnúť, či sa fragment na výpis detailných informácií spustí v novej aktivite alebo vo vedľajšom stĺpci v tej istej aktivite.

Kompletný zdrojový kód fragmentu so zoznamom štátov je v súbore ZoznamFragment.java.

public class ZoznamFragment extends ListFragment

{

protected static String[] staty = new String[] { "Albánsko", "Belgicko",

"Bielorusko"};

private SelectedListener selListener;

@Override

public void onActivityCreated(Bundle savedInstanceState)

{

super.onActivityCreated(savedInstanceState);

Context ctx = getActivity();

setListAdapter(new ArrayAdapter(ctx, R.layout.nazov, staty));

}

@Override

public void onAttach(Activity activity)

{

super.onAttach(activity);

try

{

selListener = (SelectedListener) activity;

} catch (ClassCastException e)

{

throw new ClassCastException(activity.toString()

+ " nie je implementovany listener");

}

}

@Override

public void onListItemClick(ListView l, View v, int pozice, long id)

{

selListener.onSelected(pozice);

}

public interface SelectedListener

{

public void onSelected(int vyber);

}

}

Aktivity na zapuzdrenie fragmentov

Fragmenty musia byť vložené v aktivitách. Po vytvorení projektu sa automaticky vytvorila hlavná aktivita. Fragment môžete do aktivity vložiť buď pomocou layoutu, alebo dynamicky pomocou kódu. Táto metóda umožňuje odovzdať fragmentu údaje, napríklad index vybranej položky, priamo pri vytvorení v aktivite.

Aby bola aplikácia čo najjednoduchšia, nepoužijeme ako rozhodovacie kritérium o tom, či aplikácia zobrazí každý fragment v samostatnej aktivite alebo obidva fragmenty v rámci jednej aktivity, rozlíšenie ani rozmery displeja, ale orientáciu zariadenia. V režime „na výšku" sa každý fragment zobrazí v samostatnej aktivite a v režime „na šírku" sa obidva fragmenty zobrazia v rámci hlavnej aktivity. Uvidíte, že v mnohých prípadoch to nie je zlá voľba, pretože displeje moderných telefónov majú vysoké rozlíšenie, typické pre tablety spred dvoch rokov.

Hlavná aktivita aplikácie bude obsahovať dva súbory XML s definíciami layoutu, umiestnené v zložkách /res/layout/ a /res/layout-land/. Systém si podľa orientácie zariadenia vyberie vhodný súbor.

Vytvorte v zložke res vnorenú zložku layout-land a v nej súbor typu Android XML s názvom activity_zoznam_zastupitelstiev.xml.

Kompletné definičné súbory layoutov hlavnej aktivity budú

/res/layout/activity_zoznam_zastupitelstiev.xml

android:layout_width="match_parent" android:layout_height="match_parent">

android:id="@+id/zoznam"

android:layout_width="match_parent"

android:layout_height="match_parent" />

/res/layout-land/ activity_zoznam_zastupitelstiev.xml

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="horizontal" >

android:id="@+id/zoznam"

android:layout_weight="2"

android:layout_width="0px"

android:layout_height="match_parent" />

android:id="@+id/detail"

android:layout_weight="3"

android:layout_width="0px"

android:layout_height="match_parent" />

Nastavenie atribútov layout_weight definuje horizontálne rozdelenie plochy obrazovky medzi fragmenty v pomere 1:3, pričom širší bude fragment na zobrazenie detailných informácií.

Detail aktivity bude využívať nový FrameLayout. Vytvorte v zložke /res/layout/ nový androidový súbor detail_activity.xml, pričom v dialógu na jeho vytvorenie označte voľbu FrameLayout. Aby bolo možné layout identifikovať, treba mu doplniť identifikátor.

android:layout_width="match_parent"

android:layout_height="match_parent"

android:id="@+id/detailAct">

Pri orientácii na šírku vystačíte s hlavnou aktivitou, pomocou ktorej zobrazíte fragment zoznamu objektov a vedľa neho fragment s detailmi o vybranom fragmente. Na telefóne budete potrebovať ďalšiu aktivitu na zobrazenie detailov.

DetailActivity.java

public class DetailActivity extends FragmentActivity {

public static final String VYBER = "vyber";

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_detail);

Intent i = getIntent();

int id = i.getIntExtra(VYBER, 0);

DetailFragment f = DetailFragment.newInstance(id);

getSupportFragmentManager().beginTransaction().add(R.id.detailAct, f).commit();

}

}

A napokon uvedieme kompletný kód hlavnej aktivity aplikácie v súbore ZoznamZastupitelstiev.java. V tejto aktivite sa podľa id layoutu hlavnej aktivity zisťuje, či sa použije jednostĺpcový alebo dvojstĺpcový layout.

import android.support.v4.app.FragmentActivity;

import android.support.v4.app.FragmentTransaction;

public class ZoznamZastupitelstiev extends FragmentActivity implements

ZoznamFragment.SelectedListener

{

private boolean dvaPanely;

@Override

protected void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_zoznam_zastupitelstiev);

dvaPanely = findViewById(R.id.detail) != null;

}

@Override

public void onSelected(int vyber)

{

//na sirku - dva fragmenty vedla seba

if (dvaPanely)

{

DetailFragment frg = DetailFragment.newInstance(vyber);

FragmentTransaction frgt = getSupportFragmentManager()

.beginTransaction();

frgt.replace(R.id.detail, frg);

frgt.addToBackStack(null);

frgt.commit();

} else

{ // na vysku - jeden fragment

Intent i = new Intent(this, DetailActivity.class);

i.putExtra(DetailActivity.VYBER, vyber);

startActivity(i);

}

}

}

Ak ste nezabudli pridať DetailActivity do aplikačného manifestu v súbore AndroidManifest.xml, môžete aplikáciu otestovať. Otestujte zobrazovanie Zoznam - Detail pri orientácii zariadenia na výšku, keď by sa mal zobraziť fragment s detailnými informáciami v samostatnej aktivite. Pri orientácii zariadenia na šírku by sa mali zobraziť obidva fragmenty vedľa seba. Na zmenu orientácie emulátora použite klávesovú skratku Ctrl - F12.

fragmenty4.png

Test aplikácie pri orientácii zariadenia na výšku

fragmenty5.png

Test aplikácie pri orientácii zariadenia na šírku

V budúcom pokračovaní sa budeme venovať práci s údajmi vo formátoch XML a JSON.



Nechajte si posielať prehľad najdôležitejších správ emailom

Žiadne komentáre

Vyhľadávanie

Kyocera - prve-zariadenia-formatu-a4-s-vykonom-a3

Najnovšie videá