FragmentActivity

Transkrypt

FragmentActivity
W androidzie można tworzyć dynamiczne interfejsy poprzez łączenie w
moduły komponentów UI z aktywnościami. Moduły takie tworzy się za
pomocą klasy Fragment, która zachowuje się
jak zagnieżdżone
aktywności definiujące własne layouty oraz zarządzające własnym cyklem
życia.
Kiedy fragment określa własny layout, można skonfigurować go w różne
kombinacje z innymi fragmentami wewnątrz aktywności w celu
zmodyfikowania konfiguracji layoutu na innych ekranach.
Fragmenty są wspierane od Androida 1.6
Tworzenie fragmentu
Fragmenty są częścią aktywności która posiada własny cykl życia,
otrzymuje własne zdarzenia i która może być dodana i wyłączana podczas
działania aktywności nadrzędnej.
Support Library
Support library jest zbiorem kodu który zawiera metody umożliwiające
utrzymanie wstecznej kompatybilności ze starszymi wersjami Androida.
Każda biblioteka jest kompatybilna ze specyficznym poziomem API. Dla
przykładu nasz program będzie kompatybilny z Android 1.6, czyli API
level 4 oraz w górę. Oznacza to, że musimy za pomocą SDK Managera
doinstalować .
W managerze wchodzimy w 'Extras', klikamy „Android support library” i
instalujemy.
Aby móc wykorzystać tą bibliotekę w projekcie:
• Tworzymy folder libs/ w naszym projekcie
• Kopiujemy odpowiedni plik JAR z SDK
(extras/android/support/v4/android-support-v4.jar) androida do folderu
libs/
• Prawym przyciskiem na JAR i wybieramy Build Path → Add to Build
Path
Oczywiście możemy wykorzystać class Fragment wbudowaną w API bez
wykorzystywania Suport Library – odcinamy sobie wtedy jednak
kompatybilność ze wszystkimi wersjami starszymi od API level 11.
Tworzenie fragmentu
Aby stworzyć fragment musimy rozszerzyć klasę Fragment a potem
nadpisać podstawowe metody cyklu życiowego w sposób analogiczny do
tego, co robiliśmy z klasą Activity.
Jedyną wymaganą metodą do uruchomienia Fragmentu jest nadpisanie
klasy onCreateView():
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.ViewGroup;
public class ArticleFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Zwieksz layout o dodawany fragment
return inflater.inflate(R.layout.article_view, container, false);
}
}
Dodanie Fragmentu do aktywności wykorzystując XML
Każda instancja klasy Fragment musi być związana z klasą rodzicem –
FragmentActivity co można uzyskać definiując każdy fragment
aktywności w pliku XML.
FragmentActivity jest aktywnością dostarczaną z Support Library dla API
starszych niż 11. W przypadku docelowego API będącego na poziomie 11
lub więcej, można wykorzystać normalną klasę Activity.
Przykład layoutu który dodaje dwa fragmenty do aktywności gdy ekran jest
uznawany za duży („large”):
res/layout-large/news_articles.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<fragment android:name="com.example.android.fragments.HeadlinesFragment"
android:id="@+id/headlines_fragment"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<fragment android:name="com.example.android.fragments.ArticleFragment"
android:id="@+id/article_fragment"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
Następnie musimy zastosować layout w aktywności:
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.news_articles);
}
}
Dodając fragment do layoutu za pomocą pliku XML nie możemy usunąć
fragmentu w czasie działania aplikacji – aby móc zamieniać fragmenty w
czasie interakcji z użytkownikiem należy dodać wszystkie potrzebne
fragmenty w momencie startowania aplikacji.
Budowanie elastycznego UI
Budując aplikację wspierającą duża ilość rozmiarów ekranów możemy
wykorzystywać te same fragmenty w różnych konfiguracjach layoutów.
Dodawanie fragmentu do aktywności w czasie działania aplikacji
Zamiast dodawać fragment do aktywności za pomocą pliku layoutu
możemy dodać fragment do aktywności w czasie działania aplikacji.
Wykorzystuje się to do zmiany fragmentów podczas działania aktywności.
Aby
dodać/usunąć
fragment
musimy
zastosować
klasę
FragmentManager, stworzyć transakcję: FragmentTransaction, która
pozwala nam między innymi dodać, usunąć bądź zamienić fragmenty.
Fragmenty które chcemy zastępować bądź usuwać powinniśmy dodawać
gdy aktywność jest w stanie onCreate().
Fragmenty muszą posiadać pojemnik View wewnątrz layouta. W
pojemniku tym znajdą się elementy fragmentu:
res/layout/news_articles.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Aby wygenerować transakcję musimy odwołać się wewnątrz aktywności
do getSupportFragmentManager(). Otrzymując FragmentManagera
możemy wywołać z niego metodę beginTransaction() którą tworzymy
FragmentTransaction. Następnie możemy wywołać z niego metodę add() i
dodać fragment.
Za pomocą FragmentTransaction możemy wykonać kilka transakcji w
aktywności, kiedy ustawimy wszystko tak jak chcemy, wywołujemy
commit().
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.news_articles);
// Sprawdzamy czy aktywnosc uzywa layoutu z
// fragment containerem
if (findViewById(R.id.fragment_container) != null) {
// Jesli wychodzimy z innego stanu odtwarzajacego aktywnosc
// nie musimy nic robic i powinnismy wywolac return
// poniewaz mogą powstac nachodzace na siebie fragmenty
if (savedInstanceState != null) {
return;
}
// Nowy fragment
HeadlinesFragment firstFragment = new HeadlinesFragment();
//Pobierz dodatkowe instrukcje z Intenta i przenies je do fragmentu
firstFragment.setArguments(getIntent().getExtras());
// Dodaj fragment do layoutu 'fragment_container'
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, firstFragment).commit();}}}
Zastępowanie fragmentu innym:
Procedura zmiany jest podobna do dodawania, ale zamiast .add()
stosujemy metodę replace().
Zamieniając fragmenty należy umożliwić użytkownikowi powrócić do
poprzedniego stanu. Aby umożliwić taką nawigację wstecz należy wywołać
addToBackStack() przed commitowaniem transakcji.
W momencie usuwania bądź zastępowania fragmentu, przy wywołaniu
metody addToBackStack(), fragment ten jest stopowany, a nie niszczony.
W momencie nawigacji wstecz fragment restartuje się. Gdy nie dodamy tej
transakcji do stosu wówczas fragment jest niszczony.
AddToBackStack() przyjmuje dodatkowy parametr typu string który
pozwala nadać unikatowe imię transakcji.
// Stwórz fragment i wskaz co powinien wyswietlac
ArticleFragment newFragment = new ArticleFragment();
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
newFragment.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
//Zastąp cokolwiek znajduje się w fragment_container za pomoca newFragment. Dodaj transakcje
// do stosu
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit!
transaction.commit();
Komunikacja z innymi fragmentami
Każdy fragment powinien być tworzony jako samo-zawierający się,
modularny komponent który implementuje swój layout oraz zachowanie.
Po stworzeniu takich fragmentów możemy je doczepiać do aktywności i
połączyć z logiką aplikacji.
Aby umożliwić komunikację między fragmentami musimy zastosować
komunikację przez Aktywność, fragmenty nigdy nie mogą komunikować
się bezpośrednio ze sobą.
Tworzenie interfejsu
Aby umożliwić komunikowanie Fragmentu z Aktywnością należy
zdefiniować interfejs w klasie Fragment i zaimplementować go wewnątrz
Aktywności. Fragment generuje interfejs w metodzie onAttach():
public class HeadlinesFragment extends ListFragment {
OnHeadlineSelectedListener mCallback;
// Glowna aktywnosc musi implementowac ten interfejs
public interface OnHeadlineSelectedListener {
public void onArticleSelected(int position);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Upewniamy sie ze aktywnosc glowna implementuje interfejs
// jesli nie, wyrzuca wyjatek
try {
mCallback = (OnHeadlineSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
}
Teraz fragment może wysyłać wiadomości wywołując onArticleSelected()
wykorzystując instancje mCallback interfejsu
OnHeadLineSelectedListener.
Na przykład, gdy użytkownik kliknie element listy, fragment wykorzystuje
interfejs aby wysłać zdarzenie do głównej aktywności:
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// wyslij informacje do glownej aktywnosci
mCallback.onArticleSelected(position);
}
Implementacja interfejsu:
Aby otrzymać informację z fragmentu, główna aktywność musi
zaimplementować interfejs zdefiniowany w klasie fragmentu, dla
przykładu:
public static class MainActivity extends Activity
implements HeadlinesFragment.OnHeadlineSelectedListener{
...
public void onArticleSelected(int position) {
// Uzytkownik wybral jakiś element z listy,
// Kod w tym miejscu powinien zrobic cos aby wyswietlic
}
}
Dostarczanie wiadomości do fragmentu:
Główna aktywność może dostarczać wiadomości do fragmentu poprze z
tworzenie instancji Fragmentu za pomocą findFragmentById(), a potem
wywołując jej publiczne metody.
public static class MainActivity extends Activity
implements HeadlinesFragment.OnHeadlineSelectedListener{
...
public void onArticleSelected(int position) {
// Uzytkownik wybral z listy artykul w HeadlineFragment
// Wyswietl artykul
ArticleFragment articleFrag = (ArticleFragment)
getSupportFragmentManager().findFragmentById(R.id.article_fragment);
if (articleFrag != null) {
// Jesli fragment artykulu jest dostepny, jestesmy w podwojnym layoucie
// Zaktualizuj fragment wywolujac jego metode
articleFrag.updateArticleView(position);
} else {
// W innym przypadku jestesmy w pojedyncyzm layoucie i musimy zamieniac fragmenty
// Stworz fragment i przekaz mu argumenty dla wybranego artykulu
ArticleFragment newFragment = new ArticleFragment();
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
newFragment.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Zamien rzeczy z fragment_containera na newFragment, zapamietaj poprzedni stan
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
}
}

Podobne dokumenty