W tej lekcji:
Do przeczytania:
Do wypróbowania:
Pobierz przykładowy interfejs.
Aby mieć możliwość ponownego wykorzystania fragmentów interfejsu, musisz zbudować każdy z nich w formie w pełni samodzielnego, modułowego komponentu, definiującego własny szablon i zachowanie. Kiedy już zdefiniujesz takie fragmenty wielokrotnego użytku, możesz powiązać je z jakąś aktywnością i połączyć z kodem sterującym aplikacją w cały interfejs użytkownika.
Często fragmenty muszą się ze sobą komunikować, np. by zmienić swoją treść w zależności od zdarzenia użytkownika. Komunikacja między fragmentami odbywa się poprzez powiązaną z nimi aktywność, nigdy bezpośrednio.
Definiowanie interfejsu
Aby umożliwić komunikację fragmentu z nadrzędną aktywnością, możesz zdefiniować interfejs w klasie fragmentu, a następnie zaimplementować go w aktywności. Fragment przechwyci implementację interfejsu podczas wykonywania metody cyklu życia onAttach()
, a następnie wywoła metody interfejsu w celu skomunikowania się z aktywnością.
Oto przykład komunikacji pomiędzy fragmentem a aktywnością:
public class HeadlinesFragment extends ListFragment {
OnHeadlineSelectedListener mCallback;
// aktywność będąca kontenerem musi zaimplementować ten interfejs
public interface OnHeadlineSelectedListener {
public void onArticleSelected(int position);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// upewniam się, że aktywność-kontener zaimplementowała
// interfejs z metody zwrotnej; jeśli nie, zostanie zgłoszony wyjątek
try {
mCallback = (OnHeadlineSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
...
}
Teraz fragment może przekazywać aktywności komunikaty poprzez wywołanie metody onArticleSelected()
(lub innych metod interfejsu) za pomocą wystąpienia mCallback
interfejsu OnHeadlineSelectedListener
.
Poniższy przykład przedstawia metodę fragmentu wywoływaną po kliknięciu przez użytkownika pozycji z listy. Fragment przekazuje zdarzenie nadrzędnej aktywności za pomocą interfejsu zwrotnego.
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// wysyła zdarzenie do aktywności hostującej
mCallback.onArticleSelected(position);
}
Implementacja interfejsu
Aby otrzymać z fragmentu wywołania zwrotne zdarzenia, aktywność hostująca musi zaimplementować interfejs zdefiniowany w klasie fragmentu.
Przykładowo ta aktywność implementuje interfejs z powyższego przykładu:
public static class MainActivity extends Activity
implements HeadlinesFragment.OnHeadlineSelectedListener{
...
public void onArticleSelected(int position) {
// użytkownik wybiera nagłówek artykułu z fragmentu HeadlinesFragment
// zrób coś, żeby wyświetlić artykuł
}
}
Przekazywanie wiadomości do fragmentu
Aktywność hostująca może przekazać fragmentowi wiadomość poprzez przechwycenie jego instancji i wywołanie metody findFragmentById()
, a następnie bezpośrednio wywołując publiczne metody fragmentu.
Wyobraź sobie na przykład, że powyższa aktywność zawiera jeszcze jeden fragment, który służy do wyświetlania elementu określonego przez dane zwrócone w powyższej metodzie zwrotnej. W takim wypadku aktywność może przekazać informacje otrzymane od metody zwrotnej do fragmentu, który wyświetli żądany element:
public static class MainActivity extends Activity
implements HeadlinesFragment.OnHeadlineSelectedListener{
...
public void onArticleSelected(int position) {
// użytkownik wybiera nagłówek artykułu z fragmentu HeadlinesFragment
// zrób coś, żeby wyświetlić artykuł
ArticleFragment articleFrag = (ArticleFragment)
getSupportFragmentManager().findFragmentById(R.id.article_fragment);
if (articleFrag != null) {
// jeśli fragment artykułu jest dostępny, interfejs będzie dwupanelowy…
// wywołaj metodę we fragmencie ArticleFragment, aby zaktualizować jego zawartość
articleFrag.updateArticleView(position);
} else {
// w przeciwnym razie trzeba będzie podmienić fragmenty, bo bieżący szablon jest jednopanelowy…
// utwórz fragment i przekaż mu wybrany artykuł w formie argumentu
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 tym fragmentem
// i dodaj transakcję do stosu tylnego, aby użytkownik miał opcję powrotu
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// potwierdź transakcję
transaction.commit();
}
}
}