Budowa elastycznego interfejsu użytkownika

24 maja 2015
1 gwiadka2 gwiazdki3 gwiazdki4 gwiazdki5 gwiazdek

W tej lekcji:

  1. Dodawanie fragmentu do aktywności w czasie wykonywania
  2. Zastępowanie jednego fragmentu innym

Do przeczytania:

Do wypróbowania:

Pobierz przykładowy interfejs.

Jeśli projektujesz aplikację z myślą o obsłudze ekranów o różnych rozmiarach, możesz wykorzystać te same fragmenty w różnych konfiguracjach, tak by zapewnić użytkownikowi optymalny interfejs w zależności od dostępnego na ekranie miejsca.

Na przykład na telefonie komórkowym najlepszą opcją może być interfejs jednopanelowy wyświetlający tylko jeden fragment na raz. Z kolei na tablecie, dysponującym szerszym ekranem, na którym można wyświetlić więcej informacji, lepszym wyjściem może być ustawienie fragmentów obok siebie.

różne konfiguracje fragmentów UI Androida

Rysunek 1. Dwa fragmenty tej samej aktywności wyświetlane w różnych konfiguracjach na różnych rozmiarowo ekranach. Na dużym ekranie obydwa fragmenty są umieszczone jeden obok drugiego, zaś ekran telefonu może pomieścić tylko jeden fragment. Fragmenty są zatem zamieniane w czasie poruszania się użytkownika po aplikacji.

Klasa FragmentManager zawiera metody umożliwiające zaprojektowanie dynamicznego interfejsu poprzez dodawanie, usuwanie i zamienianie fragmentów aktywności w czasie wykonywania.

Dodawanie fragmentu do aktywności w czasie wykonywania

Zamiast definiować fragmenty aktywności w pliku szablonu — za pomocą elementu <fragment>, tak jak pokazano w lekcji poprzedniej — można je dodawać do aktywności w czasie wykonywania. Jest to niezbędne, jeśli planujesz zamieniać fragmenty w czasie istnienia aktywności.

Do wykonania transakcji, np. dodania lub usunięcia elementu, konieczne jest skorzystanie z klasy FragmentManager w celu utworzenia egzemplarza klasy FragmentTransaction — dostarczy on API potrzebny do dodania, usunięcia czy zamienienia fragmentów lub wykonania innych transakcji.

Jeśli aktywność umożliwia usuwanie i zamienianie fragmentów, należy dodać początkowy fragment (lub kilka z nich) do aktywności podczas wykonywania metody onCreate().

Co ważne — zwłaszcza w przypadku fragmentów dodawanych w czasie wykonywania — fragment musi mieć w szablonie swój kontener View, w którym będzie przechowywany szablon fragmentu.

Poniższy szablon stanowi alternatywną wersję szablonu zaprezentowanego w poprzedniej lekcji, w którym wyświetlany jest tylko jeden fragment na raz. Aby podmienianie fragmentów było możliwe, szablon aktywności zawiera pustą klasę FrameLayout, która pełni funkcję kontenera dla fragmentów.

Warto zwrócić uwagę, że nazwa pliku jest taka jak nazwa szablonu z poprzedniej lekcji, jednak katalog szablonu nie zawiera kwalifikatora large. Szablon jest zatem wykorzystywany na urządzeniach o mniejszych ekranach, gdzie jest zbyt mało miejsca na jednoczesne wyświetlenie obydwu fragmentów.

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" />

Wewnątrz aktywności wywołaj metodę getSupportFragmentManager(), aby pobrać klasę FragmentManager korzystającą z API z biblioteki pomocniczej. Następnie wywołaj metodę beginTransaction() w celu utworzenia transakcji FragmentTransaction i dodaj fragment za pomocą metody add().

Korzystając z tego samego egzemplarza klasy FragmentTransaction można wykonać wiele transakcji na fragmentach. Kiedy już będziesz gotowy na wprowadzenie zmian, musisz wywołać metodę commit().

Oto przykład, jak można dodać fragment do poprzedniego szablonu:

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);

        // sprawdź, czy aktywność korzysta z wersji szablonu z kontenera
        // fragment_container szablonu FrameLayout
        if (findViewById(R.id.fragment_container) != null) {

            // Jeśli jednak przywracamy szablon z poprzedniego stanu,
            // to nie musimy nic robić; zostanie wykonane polecenie return, w przeciwnym razie
            // fragmenty mogłyby się na siebie nakładać
            if (savedInstanceState != null) {
                return;
            }

            // tworzy nowy fragment, który zostanie umieszczony w szablonie aktywności
            HeadlinesFragment firstFragment = new HeadlinesFragment();
            
            // jeśli aktywność została uruchomiona za pomocą specjalnych instrukcji z
            // intencji, przekaż do fragmentu za pośrednictwem intencji dane w postaci argumentów
            firstFragment.setArguments(getIntent().getExtras());
            
            // dodaj fragment do kontenera fragment_container szablonu FrameLayout
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.fragment_container, firstFragment).commit();
        }
    }
}

Ponieważ fragment został dodany do kontenera FrameLayout w czasie wykonywania — a nie zdefiniowany w szablonie aktywności za pomocą elementu <fragment> — można go w aktywności usunąć lub zamienić z innym fragmentem.

Zastępowanie jednego fragmentu innym

Procedura zamienia fragmentów przypomina usuwanie, jednak zamiast metody add() potrzebna jest metoda replace().

Pamiętaj, że przy okazji wykonywania transakcji na fragmentach, np. usuwania czy dodawania, często warto umożliwić użytkownikowi opcję „powrotu”, która cofnie zmianę. W tym celu należy wywołać metodę addToBackStack() przed potwierdzeniem transakcji FragmentTransaction.

Jeśli usuwasz lub zamieniasz fragmenty i dodajesz transakcję do stosu tylnego, usuwany fragment zostaje zatrzymany (a nie zniszczony). Jeśli zatem użytkownik wróci do danego fragmentu, zostanie on uruchomiony ponownie. Jeśli jednak nie dodasz transakcji do stosu tylnego to fragment, w przypadku usunięcia, zostaje zniszczony albo zamieniony.

Oto przykład ilustrujący zamienianie jednego fragmentu na inny:

// utwórz fragment i przekaż mu argument określający artykuł, który ma być  wyświetlony
ArticleFragment newFragment = new ArticleFragment();
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
newFragment.setArguments(args);

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

// zamień całą zawartość widoku fragment_container na ten fragment
// i dodaj transakcję do stosu tylnego, aby użytkownik miał możliwość powrotu
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// potwierdź transakcję
transaction.commit();

Metoda addToBackStack() przyjmuje opcjonalny parametr łańcuchowy, który określa unikalną nazwę danej transakcji. Nazwa ta potrzebna jest jedynie jeśli planujesz wykonać jakieś zaawansowane operacje na fragmentach z wykorzystaniem API elementu FragmentManager.BackStackEntry.

Autor: Google

Źródło: http://developer.android.com/training/basics/fragments/fragment-ui.html

Tłumaczenie: Joanna Liana

Treść tej strony dostępna jest na zasadach licencji CC BY 2.5

Dyskusja

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *