Migracja interfejsu do układów elastycznych

Aplikacje na Androida muszą obsługiwać stale rosnący ekosystem urządzeń. Interfejs aplikacji powinien reagować na różne rozmiary ekranów, a także różne orientacje i stany urządzeń.

Podstawą elastycznego interfejsu użytkownika jest elastyczność i ciągłość działania.

Elastyczność odnosi się do układów, które pozwalają optymalnie wykorzystać dostępną przestrzeń i dostosowywać ją w razie zmiany. Korekty mogą przyjmować różne formy: wystarczyć zwiększenie rozmiaru pojedynczego widoku, przesunąć widoki w taki sposób, aby znalazły się w bardziej dostępnych miejscach, pokazać lub ukryć dodatkowe widoki, a także łączyć te kategorie.

Ciągłość oznacza bezproblemowe przełączanie się między oknami. Niezależnie od tego, w jaki sposób użytkownik jest zaangażowany, nie powinno to powodować przerwy w działaniu. Zmiana rozmiaru może im towarzyszyć zniszczenie i odtworzenie całej hierarchii widoków, dlatego ważne jest, aby użytkownik nie utracił swojego miejsca ani swoich danych.

Czego unikać

Unikaj stosowania wartości sprzętowych przy podejmowaniu decyzji dotyczących układu strony. Podejmowanie decyzji na podstawie ustalonej wartości może być kuszące, ale w wielu sytuacjach nie nadają się do określania przestrzeni, z którą interfejs może pracować.

Na tablecie aplikacja może działać w trybie wielu okien, co oznacza, że udostępnia ekran innej aplikacji. W ChromeOS aplikacja może znajdować się w oknie z możliwością zmiany rozmiaru. Może istnieć nawet więcej niż 1 ekran fizyczny, na przykład składany lub z wieloma wyświetlaczami. We wszystkich tych przypadkach fizyczny rozmiar ekranu nie ma znaczenia przy podejmowaniu decyzji o wyświetlaniu treści.

Okna aplikacji o różnych rozmiarach wyświetlane na różnych urządzeniach.
Rysunek 1. Rozmiary okien mogą różnić się od rozmiaru fizycznego urządzenia lub wyświetlacza.

Z tego samego powodu unikaj blokowania aplikacji na określonych orientacji lub proporcjach obrazu. Urządzenie może mieć określoną orientację, ale same aplikacje mogą być wyświetlane w różnych orientacjach w zależności od rozmiaru okna. Na przykład na tablecie w orientacji poziomej i trybie wielu okien aplikacja może być pionowa, ponieważ jest wyższa niż szeroka.

Unikaj też sprawdzania, czy urządzenie to telefon czy tablet. Co konkretnie kwalifikuje się jako tablet, i jest w pewnym stopniu subiektywne: czy wynika z określonego rozmiaru lub współczynnika proporcji, czy też kombinacji rozmiaru i współczynnika proporcji? W miarę powstawania nowych formatów te założenia mogą się zmieniać, a rozróżnienie to staje się ważne.

Zamiast wypróbowywać dowolną z poprzednich strategii, korzystaj z punktów przerwania i klas rozmiaru okna.

Punkty przerwania i klasy rozmiaru okna

Rzeczywista część ekranu przydzielona do aplikacji to jej okno. Może zajmować cały ekran lub jego część, dlatego przy podejmowaniu ogólnych decyzji dotyczących układu aplikacji stosuj rozmiar okna.

Jeśli projektujesz pod kątem różnych formatów, postaraj się znaleźć wartości progowe, w których decyzje ogólne rozchodzą się w różnych kierunkach. W tym celu siatka układu elastycznego Material Design zapewnia punkty przerwania dla szerokości i wysokości, co umożliwia mapowanie nieprzetworzonych rozmiarów na odrębne, ustandaryzowane grupy nazywane klasami rozmiaru okna. Ze względu na powszechność przewijania w pionie większość aplikacji skupia się przede wszystkim na klasach rozmiaru szerokości. Dlatego większość aplikacji można zoptymalizować pod kątem każdego rozmiaru ekranu, obsługując tylko kilka punktów przerwania. Więcej informacji o klasach rozmiarów okien znajdziesz w artykule na temat obsługi różnych rozmiarów ekranu.

Stałe elementy interfejsu

Wytyczne dotyczące układu Material Design określają regiony, w których wyświetlane są paski aplikacji, opcje nawigacji i zawartość. Zwykle 2 pierwsze elementy to trwałe elementy interfejsu na poziomie głównym hierarchii widoków (lub bardzo blisko tego poziomu). Pamiętaj, że „trwałość” nie zawsze oznacza, że widok jest zawsze widoczny. Musi on raczej pozostać w tym samym miejscu, kiedy inne widoki treści mogą się przesunąć lub zmienić. Na przykład element nawigacji może znajdować się w przesuwanej szufladzie znajdującej się poza ekranem, ale szuflada jest zawsze tam, gdzie jest.

Elementy trwałe mogą być elastyczne i zwykle zajmują całą szerokość lub pełną wysokość okna, dlatego do decydowania o miejscu ich umiejscowienia warto używać klas rozmiarów. Ta opcja wyznacza miejsce na treść. W tym fragmencie aktywność używa dolnego paska w przypadku kompaktowych ekranów i górnego paska aplikacji dla większych ekranów. Zakwalifikowane układy korzystają z punktów przerwania szerokości, jak opisano wcześniej.

<!-- res/layout/main_activity.xml -->

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- content view(s) -->

    <com.google.android.material.bottomappbar.BottomAppBar
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        ... />
</androidx.constraintlayout.widget.ConstraintLayout>


<!-- res/layout-w600dp/main_activity.xml -->
<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        ... />

    <!-- content view(s) -->
</androidx.constraintlayout.widget.ConstraintLayout>

Treści

Po ustawieniu stałych elementów interfejsu wykorzystaj pozostałe miejsce na treść, np. używając elementu NavHostFragment w grafice nawigacji aplikacji. Dodatkowe informacje znajdziesz w sekcji Nawigacja po elastycznych interfejsach użytkownika.

Sprawdź, czy wszystkie dane są dostępne dla różnych rozmiarów

Większość platform aplikacji korzysta obecnie z modelu danych oddzielonego od komponentów Androida, które składają się na interfejs użytkownika (aktywności, fragmentów kodu i wyświetleń). W przypadku Jetpack tę rolę zazwyczaj pełnią obiekty ViewModele, które mają dodatkową zaletę przetrwania po zmianach konfiguracji (więcej informacji znajdziesz w artykule o modelu ViewModel).

Gdy implementujesz układ, który dopasowuje się do różnych rozmiarów, być może kuszący może być użycie innego modelu danych w oparciu o bieżący rozmiar. Jest to jednak sprzeczne z zasadą jednokierunkowego przepływu danych. Dane powinny płynąć w dół do widoków, a zdarzenia takie jak interakcje użytkowników – w górę. Utworzenie zależności w przeciwnym kierunku, gdzie model danych zależy od konfiguracji warstwy interfejsu, drastycznie to komplikuje. Gdy aplikacja zmieni rozmiar, musisz uwzględnić konwersję z jednego modelu danych na inny.

Zamiast tego pozwól, aby model danych obsługiwał największą klasę rozmiaru, a potem możesz selektywnie wyświetlać, ukrywać i zmieniać położenie treści w interfejsie, aby dostosować ją do bieżącej klasy rozmiaru. Poniżej znajdziesz kilka strategii, z których możesz skorzystać, podejmując decyzję o zachowaniu układu po przejściu między klasami rozmiarów.

Rozwiń treść

Układy kanoniczne: plik danych

Powiększona przestrzeń pozwala po prostu powiększyć elementy i zmienić format treści, aby były bardziej dostępne.

Powiększ kolekcje. Wiele aplikacji wyświetla kolekcję elementów w kontenerze, który można przewijać, np. RecyclerView czy ScrollView. Gdy kontener automatycznie powiększy się, może wyświetlić się więcej treści. Uważaj jednak, żeby zawartość kontenera nie została zbyt rozciągnięta lub zniekształcona. Na przykład w przypadku właściwości RecyclerView rozważ użycie innego menedżera układu, takiego jak GridLayoutManager, StaggeredGridLayoutManager lub FlexboxLayout, jeśli szerokość jest mniejsza.

Złożone i rozłożone urządzenie przedstawiające różnice w rozmieszczeniu aplikacji przez różne menedżery układu w zależności od klasy rozmiaru szerokości.
Rysunek 2. Różne menedżery układu dla różnych klas rozmiarów okien.

Poszczególne elementy mogą mieć różne rozmiary lub kształty, aby wyświetlać więcej treści i łatwiej rozróżniać granice elementów.

Wyróżniaj główny element. Jeśli układ zawiera określony punkt fokalny, np. obraz lub film, rozwijaj go, gdy okno aplikacji się rozwinie, aby utrzymać uwagę użytkownika. Pozostałe elementy pomocnicze można zmienić w widoku bohatera lub pod nim.

Układ można utworzyć na wiele sposobów, ale szczególnie nadaje się do tego celu ConstraintLayout, ponieważ zapewnia wiele sposobów ograniczania rozmiaru widoku podrzędnego – w tym wartości procentowej lub wymuszania współczynnika proporcji – oraz umieszczania elementów podrzędnych względem siebie lub innych elementów podrzędnych. Więcej informacji o wszystkich tych funkcjach znajdziesz w artykule o tworzeniu elastycznego interfejsu użytkownika przy użyciu ograniczeń układu.

Domyślnie pokazuj treść zwijaną. Jeśli jest dość wolnego miejsca, wyświetlaj treści, które w innym przypadku byłyby dostępne tylko przez dodatkową interakcję użytkownika, np. kliknięcie, przewijanie lub gesty. Dotyczy to np. treści wyświetlanych w interfejsie z kartami, gdy kompaktowy można przekształcić w kolumny lub listę, gdy jest więcej miejsca.

Rozwiń marginesy. Jeśli przestrzeń jest tak duża, że nawet po skorzystaniu z niej wszystkich treści nie uda Ci się znaleźć interesującego jej ujęcia, rozszerz marginesy układu, tak aby materiał pozostał wyśrodkowany, a poszczególne widoki miały naturalny rozmiar i odstępy między nimi.

Komponent pełnoekranowy może też przekształcić się w pływający interfejs okna dialogowego. Jest to szczególnie przydatne, gdy komponent ten wymaga wyłączności, aby wykonać natychmiastowe zadanie użytkownika, takie jak napisanie e-maila lub utworzenie wydarzenia w kalendarzu.

Standardowy telefon z wyświetlonym pełnym ekranem okna oraz rozłożonym składanym telefonem, na którym widać to samo okno co pływające okno.
Rysunek 3. Okno pełnoekranowe przekształcone w standardowe okno o średniej i rozwiniętej szerokości.

Dodaj treść

Układy kanoniczne: panel pomocniczy, widok szczegółów listy

Użyj panelu pomocy. W panelu pomocniczym wyświetlane są dodatkowe treści lub działania kontekstowe związane z główną treścią, takie jak komentarze w dokumencie czy elementy na playliście. Zwykle znajdują się one w dolnej trzeciej części ekranu, gdy się rozwinięte, lub w ostatniej trzeciej szerokości ekranu.

Gdy za mało miejsca, żeby wyświetlić panel, trzeba się zastanowić, gdzie umieścić te treści. Oto kilka alternatywnych rozwiązań:

  • Panel boczny na ostatniej krawędzi z użyciem elementu DrawerLayout
  • Dolna szuflada z użyciem: BottomSheetBehavior
  • Menu lub wyskakujące okienko dostępne po kliknięciu ikony menu
Rysunek 4. Alternatywne sposoby prezentowania dodatkowych treści w panelu pomocniczym.

Utwórz układ z 2 panelami. Na dużych ekranach może wyświetlać się kombinacja funkcji, które zwykle wyświetlają się oddzielnie na mniejszych ekranach. Częstym wzorcem interakcji w wielu aplikacjach jest wyświetlanie listy elementów, takich jak kontakty czy wyniki wyszukiwania, i przełączenie się na szczegóły elementu po jego wybraniu. Zamiast powiększać listę w przypadku większych ekranów, użyj widoku szczegółów listy, aby wyświetlić obie funkcje obok siebie w układzie 2 paneli. W przeciwieństwie do panelu pomocniczego panel szczegółów w widoku szczegółów listy jest samodzielnym elementem, który można wyświetlać niezależnie na mniejszych ekranach.

Aby zaimplementować widok szczegółów listy, użyj dedykowanego widżetu SlidingPaneLayout. Na podstawie wartości layout_width określonej dla tych 2 paneli automatycznie oblicza on, czy wystarczy miejsca na wyświetlenie obu paneli, a pozostałe miejsce można rozkładać za pomocą funkcji layout_weight. Gdy nie ma wystarczającej ilości miejsca, każdy panel korzysta z pełnej szerokości układu, a okienko szczegółów przesuwa się poza ekran lub u góry panelu listy.

Układ SlidingPaneLayout z obu panelami układu szczegółów listy na urządzeniu z szerokim ekranem.
Rysunek 5. SlidingPaneLayout z 2 panelami w szerokości po rozwinięciu i jednym panelem o małej szerokości.

W artykule Utwórz układ z 2 panelami znajdziesz więcej informacji o korzystaniu z SlidingPaneLayout. Pamiętaj też, że ten wzorzec może wpływać na strukturę wykresu nawigacyjnego (patrz Nawigacja po elastycznych interfejsach użytkownika).

Dodatkowe materiały