Elastyczne i adaptacyjne układy zapewniają optymalne wrażenia użytkownikom niezależnie od rozmiaru ekranu. Wdróż układy elastyczne lub adaptacyjne, aby aplikacja oparta na widokach obsługiwała wszystkie rozmiary, orientacje i konfiguracje wyświetlaczy, w tym konfiguracje z możliwością zmiany rozmiaru, takie jak tryb wielu okien.
Elastyczne projektowanie stron
Pierwszym krokiem w obsłudze różnych typów urządzeń jest utworzenie układu, który reaguje na zmiany ilości miejsca na ekranie dostępnego dla aplikacji.
ConstraintLayout
Najlepszym sposobem na utworzenie elastycznego układu jest użycie elementu
ConstraintLayout
jako podstawowego układu interfejsu. ConstraintLayout umożliwia określanie pozycji i rozmiaru każdego widoku na podstawie relacji przestrzennych z innymi widokami w układzie. Wszystkie widoki mogą się wtedy przesuwać i zmieniać rozmiar razem ze zmianami przestrzeni wyświetlania.
Najłatwiejszym sposobem tworzenia układu za pomocą ConstraintLayout jest użycie edytora układu w Android Studio. Edytor układu umożliwia przeciąganie nowych widoków do układu, stosowanie ograniczeń względem widoków nadrzędnych i pokrewnych oraz ustawianie właściwości widoku – wszystko to bez ręcznej edycji kodu XML.
ConstraintLayout.
Więcej informacji znajdziesz w artykule Tworzenie elastycznego interfejsu za pomocą ConstraintLayout.
Elastyczna szerokość i wysokość
Aby układ był elastyczny i dostosowywał się do różnych rozmiarów ekranu, używaj wartości wrap_content, match_parent lub 0dp (match constraint) w przypadku szerokości i wysokości komponentów widoku zamiast wartości zakodowanych na stałe:
wrap_content: widok dostosowuje swój rozmiar do zawartości.match_parent: Widok rozszerza się w widoku nadrzędnym w największym możliwym stopniu.0dp (match constraint): wConstraintLayout, podobnie jak wmatch_parent. Widok zajmuje całą dostępną przestrzeń w ramach ograniczeń widoku.
Przykład:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/lorem_ipsum" />
Ilustracja 4 pokazuje, jak szerokość i wysokość elementu TextView dostosowują się do zmiany szerokości wyświetlacza w zależności od orientacji urządzenia.
TextView,
Element TextView ustawia swoją szerokość tak, aby wypełniała całą dostępną przestrzeń (match_parent), a wysokość tak, aby dokładnie odpowiadała wysokości zawartego w nim tekstu (wrap_content), co umożliwia dostosowanie widoku do różnych wymiarów wyświetlacza i różnych ilości tekstu.
Jeśli używasz LinearLayout, możesz też rozwinąć widoki podrzędne na podstawie wagi układu, aby proporcjonalnie wypełniały dostępne miejsce. Jednak używanie wag w zagnieżdżonym elemencie LinearLayout wymaga od systemu wykonania wielu przebiegów układu, aby określić rozmiar każdego widoku, co spowalnia działanie interfejsu.
ConstraintLayout może tworzyć prawie wszystkie układy możliwe w przypadku elementu
LinearLayout bez wpływu na wydajność, więc przekonwertuj zagnieżdżony element
LinearLayout na element
ConstraintLayout. Następnie możesz zdefiniować układy ważone za pomocą łańcuchów ograniczeń.
Projektowanie adaptacyjne
Układ aplikacji powinien zawsze dostosowywać się do różnych rozmiarów wyświetlacza. Nawet elastyczny układ nie zapewnia jednak najlepszych wrażeń na każdym urządzeniu ani w trybie wielu okien. Na przykład interfejs zaprojektowany na telefon prawdopodobnie nie zapewnia optymalnej wygody na tablecie. Projektowanie adaptacyjne zapewnia alternatywne układy zoptymalizowane pod kątem różnych wymiarów wyświetlania.
SlidingPaneLayout w interfejsach użytkownika typu szczegółowa lista
Interfejs szczegółowej listy zwykle zapewnia różne wrażenia użytkownika na ekranach o różnych rozmiarach. Na dużych ekranach panele listy i szczegółów są zwykle wyświetlane obok siebie. Po wybraniu elementu na liście informacje o nim są wyświetlane w panelu szczegółów bez zmiany interfejsu – oba panele pozostają obok siebie. Na małych ekranach oba panele są jednak wyświetlane oddzielnie, a każdy z nich zajmuje cały obszar wyświetlania. Gdy wybierzesz element w panelu listy, panel szczegółów (zawierający informacje o wybranym elemencie) zastąpi panel listy. Przechodzenie wstecz zastępuje panel szczegółów listą.
SlidingPaneLayout
zarządza logiką określania, które z 2 rodzajów wrażeń użytkownika są odpowiednie dla bieżącego rozmiaru okna:
<?xml version="1.0" encoding="utf-8"?>
<androidx.slidingpanelayout.widget.SlidingPaneLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="280dp"
android:layout_height="match_parent"
android:layout_gravity="start" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_weight="1"
app:defaultNavHost="true"
app:navGraph="@navigation/item_navigation" />
</androidx.slidingpanelayout.widget.SlidingPaneLayout>
Atrybuty layout_width i layout_weight 2 widoków danych zawartych w SlidingPaneLayout określają działanie SlidingPaneLayout. W tym przykładzie, jeśli okno jest wystarczająco duże (ma co najmniej 580 dp szerokości), aby wyświetlić oba widoki, panele są wyświetlane obok siebie. Jeśli jednak szerokość okna jest mniejsza niż 580 dp, panele przesuwają się jeden na drugi, aby każdy z nich zajmował całe okno aplikacji.
Jeśli szerokość okna jest większa niż łączna określona minimalna szerokość (580 dp), do proporcjonalnego określania rozmiaru obu paneli można używać wartości layout_weight. W tym przykładzie panel listy ma zawsze szerokość 280 dp, ponieważ nie ma wagi.
Panel szczegółów zawsze wypełnia jednak całą przestrzeń poziomą powyżej 580 dp ze względu na ustawienie layout_weight widoku.
Alternatywne zasoby układu
Aby dostosować projekt interfejsu do bardzo różnych rozmiarów wyświetlaczy, użyj alternatywnych układów zidentyfikowanych przez kwalifikatory zasobów.
Możesz udostępniać adaptacyjne układy dostosowane do ekranu, tworząc dodatkowe katalogi res/layout/ w kodzie źródłowym aplikacji. Utwórz katalog dla każdej konfiguracji ekranu, która wymaga innego układu. Następnie do nazwy katalogu layout dodaj kwalifikator konfiguracji ekranu (np. layout-w600dp w przypadku ekranów o dostępnej szerokości 600 dp).
Kwalifikatory konfiguracji reprezentują widoczną przestrzeń wyświetlania dostępną dla interfejsu aplikacji. System bierze pod uwagę wszelkie elementy dekoracyjne systemu (np. pasek nawigacyjny) i zmiany konfiguracji okna (np. tryb wielu okien) podczas wybierania układu aplikacji.
Aby utworzyć alternatywne układy w Android Studio, zapoznaj się z artykułem Używanie wariantów układu do optymalizacji pod kątem różnych ekranów w sekcji Tworzenie interfejsu za pomocą widoków.
Kwalifikator najmniejszej szerokości
Kwalifikator rozmiaru ekranu najmniejsza szerokość umożliwia udostępnianie alternatywnych układów na wyświetlaczach o minimalnej szerokości mierzonej w pikselach niezależnych od gęstości (dp).
Opisując rozmiar ekranu jako miarę dp, Android umożliwia tworzenie układów przeznaczonych dla określonych wymiarów wyświetlacza bez względu na różne gęstości pikseli.
Możesz na przykład utworzyć układ o nazwie main_activity zoptymalizowany pod kątem telefonów i tabletów, tworząc różne wersje pliku w różnych katalogach:
res/layout/main_activity.xml # For phones (smaller than 600dp smallest width) res/layout-sw600dp/main_activity.xml # For 7" tablets (600dp wide or wider)
Kwalifikator najmniejszej szerokości określa mniejszy z 2 boków wyświetlacza, niezależnie od bieżącej orientacji urządzenia. Jest to więc sposób na określenie ogólnego rozmiaru wyświetlacza dostępnego dla układu.
Oto jak inne wartości najmniejszej szerokości odpowiadają typowym rozmiarom ekranu:
- 320 dp: mały ekran telefonu (240 x 320 ldpi, 320 x 480 mdpi, 480 x 800 hdpi itp.)
- 480 dp: duży ekran telefonu – ok. 5 cali (480 x 800 mdpi)
- 600 dp: 7-calowy tablet (600 x 1024 mdpi)
- 720dp: tablet 10-calowy (720x1280 mdpi, 800x1280 mdpi itp.)
Na poniższym rysunku możesz zobaczyć, jak różne szerokości ekranu w jednostkach dp odpowiadają różnym rozmiarom i orientacjom ekranu.
Wartości kwalifikatora najmniejsza szerokość są podawane w jednostkach dp, ponieważ liczy się ilość miejsca na ekranie dostępnego po uwzględnieniu przez system gęstości pikseli (a nie rozdzielczość w pikselach).
Rozmiary określone za pomocą kwalifikatorów zasobów, takich jak najmniejsza szerokość, nie są rzeczywistymi rozmiarami ekranu. Określają one szerokość lub wysokość w jednostkach dp, które są dostępne w oknie aplikacji. System Android może używać części ekranu na potrzeby interfejsu systemu (np. paska systemowego u dołu ekranu lub paska stanu u góry), więc część ekranu może być niedostępna dla Twojego układu. Jeśli aplikacja jest używana w trybie wielu okien, ma dostęp tylko do rozmiaru okna, w którym jest otwarta. Gdy rozmiar okna się zmieni, nastąpi zmiana konfiguracji z nowym rozmiarem okna, co umożliwi systemowi wybranie odpowiedniego pliku układu. Dlatego rozmiary kwalifikatora zasobu, które deklarujesz, powinny określać tylko przestrzeń potrzebną aplikacji. System uwzględnia przestrzeń używaną przez interfejs systemu, gdy udostępnia miejsce na układ.
Kwalifikator dostępnej szerokości
Zamiast zmieniać układ na podstawie najmniejszej szerokości wyświetlacza, możesz go zmieniać na podstawie dostępnej szerokości lub wysokości. Możesz na przykład używać układu dwupanelowego, gdy ekran ma szerokość co najmniej 600 dp. Może się to zmieniać w zależności od tego, czy urządzenie jest w orientacji poziomej czy pionowej. W takim przypadku użyj kwalifikatora dostępna szerokość w ten sposób:
res/layout/main_activity.xml # For phones (smaller than 600dp available width)
res/layout-w600dp/main_activity.xml # For 7" tablets or any screen with 600dp available width
# (possibly landscape phones)
Jeśli dostępna wysokość jest ważna dla Twojej aplikacji, możesz użyć kwalifikatora available height. Na przykład layout-h600dp w przypadku ekranów o wysokości co najmniej 600 dp.
Kwalifikatory orientacji
Chociaż możesz obsługiwać wszystkie warianty rozmiaru, używając tylko kombinacji kwalifikatorów najmniejsza szerokość i dostępna szerokość, możesz też chcieć zmienić wrażenia użytkownika, gdy przełącza się on między orientacją pionową a poziomą.
W tym celu możesz dodać do nazw katalogów układów kwalifikatory port lub land. Pamiętaj tylko, aby kwalifikatory orientacji występowały po kwalifikatorach rozmiaru.
Przykład:
res/layout/main_activity.xml # For phones res/layout-land/main_activity.xml # For phones in landscape res/layout-sw600dp/main_activity.xml # For 7" tablets res/layout-sw600dp-land/main_activity.xml # For 7" tablets in landscape
Więcej informacji o wszystkich kwalifikatorach konfiguracji ekranu znajdziesz w omówieniu zasobów aplikacji.
Klasy rozmiarów okien
Klasy rozmiaru okna to punkty przerwania widocznego obszaru, które pomagają tworzyć adaptacyjne układy. Punkty przerwania określają obszar wyświetlania dostępny dla aplikacji jako kompaktowy, średni lub rozszerzony. Szerokość i wysokość są określane oddzielnie, więc aplikacja zawsze ma klasę rozmiaru okna dla szerokości i klasę rozmiaru okna dla wysokości.
Aby zastosować adaptacyjne układy programowo:
- Tworzenie zasobów układu na podstawie punktów przerwania klas rozmiaru okna
- Oblicz klasy rozmiarów okien aplikacji (szerokość i wysokość) za pomocą funkcji
WindowSizeClass#compute()z biblioteki Jetpack WindowManager. - Rozszerzanie zasobu układu dla bieżących klas rozmiaru okna
Więcej informacji znajdziesz w artykule Klasy rozmiaru okna.
Modułowe komponenty interfejsu korzystające z fragmentów
Projektując aplikację pod kątem różnych rozmiarów wyświetlacza, używaj fragmentów, aby wyodrębnić logikę interfejsu do osobnych komponentów. Dzięki temu unikniesz niepotrzebnego powielania zachowania interfejsu w różnych aktywnościach. Możesz wtedy łączyć fragmenty, aby tworzyć układy wielopanelowe na dużych ekranach, lub umieszczać fragmenty w osobnych aktywnościach na małych ekranach.
Na przykład wzorzec listy i szczegółów (patrz SlidingPaneLayout powyżej) można zaimplementować za pomocą jednego fragmentu zawierającego listę i drugiego fragmentu zawierającego szczegóły elementu listy. Na dużych ekranach fragmenty mogą być wyświetlane obok siebie, a na małych – pojedynczo, wypełniając ekran.
Więcej informacji znajdziesz w omówieniu fragmentów.
Osadzanie aktywności
Jeśli Twoja aplikacja składa się z wielu aktywności, osadzanie aktywności umożliwia łatwe tworzenie adaptacyjnego interfejsu.
Osadzanie aktywności umożliwia wyświetlanie wielu aktywności lub wielu instancji tej samej aktywności jednocześnie w oknie zadania aplikacji. Na dużych ekranach aktywności mogą być wyświetlane obok siebie, a na małych – jedna nad drugą.
Sposób wyświetlania aktywności w aplikacji określa się, tworząc plik konfiguracji XML, który jest używany przez system do określania odpowiedniej prezentacji na podstawie rozmiaru wyświetlacza. Możesz też wykonywać wywołania interfejsu Jetpack WindowManager API.
Osadzanie aktywności obsługuje zmiany orientacji urządzenia i urządzenia składane, układanie i rozdzielanie aktywności podczas obracania lub składania i rozkładania urządzenia.
Więcej informacji znajdziesz w artykule Osadzanie aktywności.
Rozmiary ekranu i formaty obrazu
Przetestuj aplikację na różnych rozmiarach ekranu i w różnych proporcjach, aby upewnić się, że interfejs użytkownika jest prawidłowo skalowany.
Android 10 (poziom 29 interfejsu API) i nowsze wersje obsługują szeroki zakres formatów obrazu. Składane urządzenia mogą mieć różne formaty, od wysokich i wąskich ekranów, np. 21:9 po złożeniu, po kwadratowe o proporcjach 1:1 po rozłożeniu.
Aby zapewnić zgodność z jak największą liczbą urządzeń, przetestuj aplikacje pod kątem jak największej liczby tych proporcji ekranu:
Jeśli nie masz dostępu do urządzeń o różnych rozmiarach ekranu, na których chcesz przeprowadzić testy, możesz użyć emulatora Androida, aby emulować niemal dowolny rozmiar ekranu.
Jeśli wolisz testować na prawdziwym urządzeniu, ale go nie masz, możesz skorzystać z Laboratorium Firebase, aby uzyskać dostęp do urządzeń w centrum danych Google.
Dodatkowe materiały
- Material Design – Understanding layout