Urządzenia z Androidem mają nie tylko różne rozmiary ekranów – telefony, tablety, telewizory, itp., ale mają też ekrany o różnych rozmiarach. Jeden urządzenie może mieć 160 pikseli na cal, a inne urządzenie może mieć rozmiar 480 pikseli. pikseli w tej samej przestrzeni. Jeśli nie weźmiesz pod uwagę tych różnic w gęstość pikseli, układ może się skalować w wyniku czego obrazy są rozmyte lub mogą wyświetlają się w niewłaściwym rozmiarze.
Na tej stronie dowiesz się, jak zaprojektować aplikację, aby różne gęstości pikseli dzięki zastosowaniu jednostek miary niezależnych od rozdzielczości. i dostarczanie alternatywnych zasobów mapy bitowej dla każdej gęstości pikseli.
Aby dowiedzieć się więcej o tych technikach, obejrzyj film poniżej.
Więcej informacji o projektowaniu zasobów ikon znajdziesz w wytycznych dotyczących ikon interfejsu Material Design.
Użyj pikseli niezależnych od gęstości
Unikaj używania pikseli do definiowania odległości i rozmiarów. Definiowanie wymiarów za pomocą to problem, ponieważ różne ekrany mają różną gęstość pikseli, więc ta sama liczba pikseli odpowiada różnym rozmiarom fizycznym na różnych urządzeniach.
Aby zachować widoczny rozmiar UI na ekranach o różnej gęstości, zaprojektuj UI piksele niezależne od gęstości (dp). Jeden dp to wirtualnej jednostki pikseli, która jest mniej więcej równa 1 pikselowi na ekranie o średniej gęstości. (160 dpi lub gęstość „odniesienia”). Android przekłada tę wartość na odpowiednią liczbę rzeczywistych pikseli dla danej gęstości.
Przyjrzyjmy się dwóm urządzeniom z ilustracji 1. Widok, który Szerokość 100 pikseli po lewej stronie jest dużo większa. Widok Zgodnie z definicjami szerokości 100 dp rozmiar jest taki sam na obu ekranach.
Aby zdefiniować rozmiary tekstu, możesz zamiast tego użyć funkcji skalowalność pikseli (sp) jako jednostek. Jednostka sp to domyślnie ma taki sam rozmiar jak dp, ale zmienia rozmiar w zależności od preferencji użytkownika rozmiar tekstu. Nigdy nie używaj sp dla rozmiarów układów.
Aby na przykład określić odstępy między 2 widokami, użyj dp:
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/clickme" android:layout_marginTop="20dp" />
Określając rozmiar tekstu, użyj sp:
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="20sp" />
Przelicz jednostki dp na jednostki pikseli
W niektórych przypadkach należy podawać wymiary w dp, a następnie i przekonwertować je na piksele. Konwersja jednostek dp na piksele ekranu jest taki:
px = dp * (dpi / 160)
Uwaga: nigdy nie koduj na stałe tego równania do obliczania pikseli. Zamiast tego użyj
TypedValue.applyDimension()
,
który konwertuje różne typy wymiarów (dp, sp itp.) na piksele.
Wyobraź sobie aplikację, w której rozpoznawany jest gest przewijania lub przesuwania
po przesunięciu palca użytkownika o co najmniej 16 pikseli. Na poziomie bazowym
ekranu, palec użytkownika musi przesunąć się o 16 pixels
/ 160 dpi
, co odpowiada 1/10 cala (lub 2,5 mm), przed
gest zostanie rozpoznany.
Na urządzeniu
na wyświetlaczu o dużej gęstości (240 dpi) musi się ruszać palec użytkownika
16 pixels / 240 dpi
, która
to 1/15 cala (lub 1,7 mm). Odległość jest znacznie mniejsza,
sprawia, że aplikacja wydaje się bardziej wrażliwa dla użytkownika.
Aby rozwiązać ten problem, określ próg gestów w kodzie w dp i a potem przekonwertuj je na piksele. Na przykład:
Kotlin
// The gesture threshold expressed in dp private const val GESTURE_THRESHOLD_DP = 16.0f private var gestureThreshold: Int = 0 // Convert the dps to pixels, based on density scale gestureThreshold = TypedValue.applyDimension( COMPLEX_UNIT_DIP, GESTURE_THRESHOLD_DP 0.5f, resources.displayMetrics).toInt() // Use gestureThreshold as a distance in pixels...
Java
// The gesture threshold expressed in dp private final float GESTURE_THRESHOLD_DP = 16.0f; // Convert the dps to pixels, based on density scale int gestureThreshold = (int) TypedValue.applyDimension( COMPLEX_UNIT_DIP, GESTURE_THRESHOLD_DP 0.5f, getResources().getDisplayMetrics()); // Use gestureThreshold as a distance in pixels...
Pole DisplayMetrics.density
określa współczynnik skali używany do przeliczania jednostek dp na
pikseli zgodnie z bieżącą gęstością pikseli. Na ekranie o średniej gęstości
DisplayMetrics.density
równa się
1,0, a na ekranie o dużej gęstości ma on wartość 1,5. Na ekranie o bardzo dużej gęstości
jest to 2,0, a na ekranie o małej gęstości – 0,75. Ta wartość jest
używane przez TypedValue.applyDimension()
do
podaj rzeczywistą liczbę pikseli na bieżącym ekranie.
Użyj wstępnie przeskalowanych wartości konfiguracji
Za pomocą klasy ViewConfiguration
możesz uzyskać dostęp do typowych
odległości, prędkości i czasu używane przez system Android. Na przykład plik
odległość w pikselach używana przez platformę służącą do uzyskania progu przewijania
z użytkownikiem getScaledTouchSlop()
:
Kotlin
private val GESTURE_THRESHOLD_DP = ViewConfiguration.get(myContext).scaledTouchSlop
Java
private final int GESTURE_THRESHOLD_DP = ViewConfiguration.get(myContext).getScaledTouchSlop();
Metody w funkcji ViewConfiguration
zaczynające się od prefiksu getScaled
zwrócą wartość w pikselach, która będzie wyświetlana poprawnie niezależnie od
gęstości pikseli.
Preferuj grafikę wektorową
Alternatywą dla tworzenia różnych wersji obrazu dostosowanych do różnych gęstości jest utworzyć tylko jedną grafikę wektorową. Grafika wektorowa tworzy obraz za pomocą formatu XML, definiowania ścieżek i kolorów, zamiast używać pikselowych map bitowych. W ten sposób grafikę można skalować do dowolnego rozmiaru bez skalowania artefaktów. najlepiej w przypadku ilustracji, takich jak ikony, a nie fotografie.
Obrazy wektorowe są często przesyłane jako pliki SVG (Scalable Vector Graphics), Android nie obsługuje tego formatu, więc musisz przekonwertować pliki SVG na Wektor Androida rysowalny.
Plik SVG możesz przekonwertować na obiekt rysowalny wektorowy za pomocą biblioteki Vector Asset Studio, w następujący sposób:
- W oknie Projekt kliknij prawym przyciskiem myszy katalog res i wybierz Nowe > Zasób wektorowy.
- Wybierz Plik lokalny (SVG, PSD).
Znajdź plik, który chcesz zaimportować, i wprowadź zmiany.
W oknie Asset Studio mogą pojawić się błędy co oznacza, że obiekty rysowalne wektorowe nie obsługują niektórych właściwości pliku. Mimo to nadal nie będzie można zaimportować pliku. nieobsługiwane właściwości są ignorowane.
Kliknij Dalej.
Na następnym ekranie potwierdź zbiór źródłowy, w którym chcesz umieścić plik w projekcie. i kliknij Zakończ.
W przypadku wszystkich gęstości pikseli, więc ten plik zostanie przeniesiony do domyślnego katalogu z elementami rysowania, jak w poniższym przykładzie: w hierarchii. Nie musisz używać katalogów dostosowanych do gęstości.
res/ drawable/ ic_android_launcher.xml
Więcej informacji o tworzeniu grafiki wektorowej znajdziesz w artykule o rysowaniu wektorowym. dokumentacji.
Udostępnij alternatywne mapy bitowe
Aby zapewnić dobrą jakość grafiki na urządzeniach o różnej gęstości pikseli, udostępnij wiele wersji każdej bitmapy w aplikacji – po jednej dla każdej zasobnika o odpowiedniej rozdzielczości. W przeciwnym razie Android musi się skalować. bitmapa, tak aby zajmowała tę samą widoczną przestrzeń na każdym ekranie, np. rozmycia.
W aplikacjach dostępnych jest kilka zasobników gęstości. Tabela 1 opisuje różne dostępne kwalifikatory konfiguracji i typy ekranów. których dotyczą.
Kwalifikator gęstości | Opis |
---|---|
ldpi |
Zasoby na temat ekranów o niskiej gęstości (ldpi) (ok. 120 dpi). |
mdpi |
Zasoby dla ekranów o średniej gęstości (mdpi) (ok. 160 dpi). To jest wartość bazowa gęstość danych. |
hdpi |
Zasoby dotyczące ekranów o dużej gęstości (hdpi) (ok. 240 dpi). |
xhdpi |
Zasoby dotyczące ekranów o bardzo dużej gęstości (xhdpi) (ok. 320 dpi). |
xxhdpi |
Zasoby dotyczące ekranów o bardzo dużej gęstości (xxhdpi) (ok. 480 dpi). |
xxxhdpi |
Zasoby dotyczące bardzo dużej gęstości (xxxhdpi) (ok. 640 dpi). |
nodpi |
Zasoby dla wszystkich gęstości. Są to zasoby niezależne od gęstości. System nie chce skalować zasoby otagowane tym kwalifikatorem niezależnie od gęstości bieżącego ekranu. |
tvdpi |
zasoby dotyczące ekranów o rozdzielczości od mdpi do hdpi; około
Ok. 213 dpi. Nie jest uważane za „główne” grupy gęstości. Przeznaczona jest ona głównie
dla telewizorów, a większość aplikacji go nie potrzebuje – zapewnia mdpi i hdpi
zasobów wystarcza na większość aplikacji, a system skaluje je
odpowiednie. Jeśli uznasz, że musisz udostępnić zasoby tvdpi ,
ustalając ich współczynnik proporcji 1,33 * mdpi. Na przykład obraz o wymiarach 100 x 100 pikseli dla
Ekrany mdpi mają rozdzielczość 133 x 133 piksele w przypadku rozdzielczości tvdpi. |
Aby utworzyć alternatywne obiekty rysunkowe bitmapy dla różnych gęstości, postępuj zgodnie z instrukcjami Współczynnik skalowania 3:4:6:8:12:16 między 6 podstawowymi gęstościami. Jeśli na przykład masz bitmapa rysowalna o wymiarach 48 x 48 pikseli dla ekranów o średniej gęstości. Rozmiary są następujące:
- 36 x 36 (0,75x) dla małej gęstości (ldpi)
- 48 x 48 (1,0x – poziom odniesienia) dla średniej gęstości (mdpi)
- 72 x 72 (1,5x) – wysoka gęstość (hdpi)
- 96 x 96 (2,0x) – bardzo duża gęstość (xhdpi)
- 144 x 144 (3,0x) – bardzo duża gęstość (xxhdpi)
- 192 x 192 (4,0x) – bardzo duża gęstość (xxxhdpi)
Umieść wygenerowane pliki obrazów w odpowiednim podkatalogu.
poniżej res/
:
res/ drawable-xxxhdpi/ awesome_image.png drawable-xxhdpi/ awesome_image.png drawable-xhdpi/ awesome_image.png drawable-hdpi/ awesome_image.png drawable-mdpi/ awesome_image.png
Za każdym razem, gdy odwołasz się do @drawable/awesomeimage
,
system wybiera odpowiednią bitmapę, kierując się rozdzielczością dpi ekranu. Jeśli
jeśli nie zostaną udostępnione zasoby związane z daną gęstością, system wskaże
które najlepiej pasują do reklamy i dopasowują ją do ekranu.
Wskazówka: jeśli masz zasoby, które można przeciągać
których nie chcesz skalować, np. podczas wykonywania
samodzielnie wprowadzić poprawki do obrazu
w czasie działania, a następnie umieścić je
katalogu z kwalifikatorem konfiguracji nodpi
.
Zasoby z tym kwalifikatorem są uważane za niezależne od gęstości,
system ich nie skaluje.
Więcej informacji o innych kwalifikatorach konfiguracji jak Android wybiera odpowiednie zasoby bieżącej konfiguracji ekranu, zapoznaj się z omówieniem zasobów aplikacji.
Umieść ikony aplikacji w katalogach mipmap
Podobnie jak w przypadku innych zasobów mapy bitowej musisz udostępnić wersje mapy o określonej gęstości ikonę aplikacji. Jednak niektóre Menu z aplikacjami wyświetlają ikonę aplikacji nawet w 25% większy niż jest dozwolony przez segment gęstości urządzenia.
Na przykład: jeśli zasobnik o gęstości ekranu na urządzeniu to xxhdpi, a największa ikona aplikacji
należy podać w języku drawable-xxhdpi
, menu z aplikacjami skaluje tę ikonę w górę,
przez co wydaje się mniej wyrazisty.
Aby tego uniknąć, umieść wszystkie
ikony aplikacji w katalogach mipmap
zamiast w katalogach drawable
. Nie podoba mi się
drawable
, wszystkie katalogi mipmap
zostaną zachowane w pliku APK, nawet
jeśli tworzysz pliki APK dla określonej gęstości. Pozwoli to aplikacjom uruchamiającym wybrać najlepsze
ikonę rozdzielczości, która ma być wyświetlana na ekranie głównym.
res/ mipmap-xxxhdpi/ launcher_icon.png mipmap-xxhdpi/ launcher_icon.png mipmap-xhdpi/ launcher_icon.png mipmap-hdpi/ launcher_icon.png mipmap-mdpi/ launcher_icon.png
W poprzednim przykładzie urządzenia xxhdpi możesz podać
ikonę programu uruchamiającego o większej gęstości w katalogu mipmap-xxxhdpi
.
Wskazówki dotyczące projektowania ikon znajdziesz w artykule Ikony systemowe.
Więcej informacji o tworzeniu ikon aplikacji znajdziesz w artykule Tworzenie ikon aplikacji za pomocą Image Asset Studio.
Porady dotyczące rzadkich problemów z gęstością
W tej sekcji opisaliśmy, jak Android przeprowadza skalowanie na potrzeby map bitowych dla różnej gęstości pikseli i sposobu bitmapy są rysowane w różnych gęstościach. Chyba że aplikacja modyfikuje grafikę lub występują problemy z działaniem z różną gęstością pikseli, mogą zignorować tę sekcję.
Aby lepiej zrozumieć, jak obsługiwać różne gęstości podczas manipulowania grafiką musisz wiedzieć, jak system pomaga zapewnić odpowiednią skalę map bitowych. Odbywa się to na kilka sposobów:
- Wstępne skalowanie zasobów, takich jak obiekty rysunkowe mapy bitowej
W zależności od gęstości ekranu system wykorzystuje z aplikacji. Jeśli zasoby nie są dostępne w nad prawidłową gęstością, system wczytuje zasoby domyślne i skaluje je odpowiednio w górę lub w dół. System zakłada, że zasoby domyślne (pochodzące z bez kwalifikatorów konfiguracji) są przeznaczone dla punktu odniesienia gęstości pikseli (mdpi) i dopasowuje rozmiar tych map bitowych do rozmiaru do aktualnej gęstości pikseli.
Jeśli zażądasz wymiarów wstępnie przeskalowanego zasobu, system zwróci wartości reprezentujące wymiary po skalowaniu. Na przykład bitmapa o wymiarach 50 x 50 pikseli. dla ekranu mdpi jest skalowana do 75x75 pikseli na ekranie hdpi (jeśli nie ma alternatywnego zasobu w przypadku rozdzielczości hdpi), a system raportuje ten rozmiar w ten sposób.
W niektórych sytuacjach można nie chcieć, aby Android w zasobach. Najłatwiejszym sposobem uniknięcia wstępnego skalowania jest umieszczenie zasobu w katalogu zasobów z kwalifikatorem konfiguracji
nodpi
. Na przykład:res/drawable-nodpi/icon.png
Gdy system używa mapy bitowej
icon.png
z tego folderu, nie skaluje jej na podstawie obecnej gęstości urządzeń. - Autoskalowanie wymiarów i współrzędnych w pikselach
Możesz wyłączyć wymiary i obrazy wstępnego skalowania, ustawiając opcję
android:anyDensity
na"false"
w pliku manifestu lub automatycznie dlaBitmap
przez ustawienieinScaled
na"false"
. W W tym przypadku system automatycznie skaluje wszystkie bezwzględne współrzędne pikseli oraz wartości wymiarów w momencie rysowania. Ma to na celu zapewnienie, że piksele zostaną elementy ekranu są nadal wyświetlane przy mniej więcej takim samym rozmiarze fizycznym że można je wyświetlać z wyjściową gęstością pikseli (mdpi). System obsługuje skaluje się w sposób przejrzysty do aplikacji i zgłasza skalowany piksel, z wymiarami aplikacji, a nie z wymiarami fizycznymi w pikselach.Załóżmy na przykład, że urządzenie ma ekran o dużej gęstości WVGA, który ma wymiary 480 x 800 pikseli i jest taki sam jak tradycyjny ekran HVGA, ale działa na nim aplikacja z wyłączoną funkcją przez skalowanie. W takim przypadku system „kłamuje” do aplikacji, gdy wysyła zapytanie o ekran i raportuje wymiary 320 x 533, czyli przybliżone przesunięcie mdpi dla gęstości pikseli.
Następnie, gdy aplikacja wykonuje operacje rysowania, takie jak unieważnianie prostokątów od (10,10) do (100, 100), system przekształca współrzędne, skalując je do odpowiedniej wielkości i w ten sposób unieważnia region (15,15) do (150, 150). Ta rozbieżność może powodować nieoczekiwane działanie, jeśli aplikacja bezpośrednio używa skalowanej mapy bitowej, ale uznaje się to za uzasadnione w celu zapewnienia optymalnej wydajności aplikacji. Jeśli natrafisz na znajduje się w artykule Konwertowanie jednostek dp na piksele .
Zwykle nie wyłącza się wstępnego skalowania. Najlepszy sposób obsługi wielu z zastosowaniem podstawowych metod opisanych na tej stronie.
czy aplikacja modyfikuje mapy bitowe lub bezpośrednio wchodzi w interakcję z pikselami na ekranie. w inny sposób, może być konieczne wykonanie dodatkowych czynności w celu obsługi gęstości pikseli. Jeśli na przykład reagujesz na gesty dotykowe, zliczając liczby pikseli, które krzyżuje palce, użyj odpowiedniego niezależnych od gęstości pikseli, a nie rzeczywistej liczby pikseli, ale możesz przelicz na wartość dp lub px.
Przetestuj na wszystkich gęstości pikseli
Testowanie aplikacji na wielu urządzeniach z użyciem różnych pikseli gęstości, aby zapewnić prawidłowe skalowanie interfejsu użytkownika. Testowanie na: urządzenia, gdy jest to możliwe; należy korzystać z systemu Android Emulator, jeśli nie masz dostępu do fizycznej dla różnych gęstości pikseli.
Jeśli chcesz przeprowadzać testy na urządzeniach fizycznych, i nie chcesz ich kupować, możesz skorzystać z Laboratorium Firebase, aby dostępu do urządzeń w centrum danych Google.