px — fizyczny piksel, minimalny element obrazu na ekranie urządzenia. W programowaniu mobilnym px jest używany jako podstawowa jednostka rozdzielczości ekranu i gęstości pikseli (PPI), ale praktycznie nie stosuje się go do układu interfejsów — zamiast niego używa się jednostek logicznych pt, dp i sp. Artykuł wyjaśnia, czym px różni się od jednostek logicznych, jak powiązane są rozdzielczość i PPI oraz dlaczego bezpośrednie użycie px w kodzie to antypattern.
Najważniejsze
px (pixel, picture element) — minimalny adresowalny element obrazu rastrowego lub wyświetlacza. Każdy piksel przechowuje informację o kolorze w modelu RGB (czerwony, zielony, niebieski) z głębią koloru od 8 do 10 bitów na kanał. Współczesne wyświetlacze urządzeń mobilnych zawierają miliony pikseli: iPhone 15 Pro — 3 mln, iPad Pro 12.9" — 5.6 mln pikseli.
Fizyczny rozmiar piksela zależy od gęstości wyświetlacza (PPI). Na urządzeniu z 326 PPI (iPhone 11) jeden piksel ma rozmiar około 0.078 mm. Na wyświetlaczu z 460 PPI (iPhone 15 Pro) — 0.055 mm. Im mniejszy fizyczny rozmiar piksela, tym wyższa ostrość obrazu. Gęstość pikseli bezpośrednio wpływa na wydajność renderowania: więcej pikseli = więcej pracy dla GPU.
Według danych Apple, rozdzielczość wyświetlacza iPhone 15 Pro wynosi 1179 × 2556 px przy gęstości 460 PPI. Dla porównania, iPhone SE (3rd gen) — 750 × 1334 px przy 326 PPI. Różnica w całkowitej liczbie pikseli jest prawie 3-krotna, co wyjaśnia wyższe wymagania względem GPU w modelach Pro.
Rozdzielczość ekranu — liczba fizycznych pikseli w poziomie i pionie. Zapisuje się w formacie szerokość × wysokość, np. 1179 × 2556 px. Rozdzielczość jest fundamentalną cechą wyświetlacza, której nie można zmienić programowo — jest ustalona na poziomie sprzętu i matrycy.
| Urządzenie | Rozdzielczość (px) | PPI | Proporcje ekranu |
|---|---|---|---|
| iPhone SE (3rd gen) | 750 × 1334 | 326 | 16:9 |
| iPhone 14 | 1170 × 2532 | 460 | 19.5:9 |
| iPhone 15 Pro Max | 1290 × 2796 | 460 | 19.5:9 |
| Samsung Galaxy S24 Ultra | 1440 × 3120 | 505 | 19.5:9 |
| Google Pixel 8 Pro | 1344 × 2992 | 490 | 20:9 |
| iPad Pro 12.9" | 2048 × 2732 | 264 | 4:3 |
Rozdzielczości w pikselach nie należy mylić z logicznym rozmiarem ekranu (w pt dla iOS lub dp dla Android). Na przykład iPhone 14 ma logiczny rozmiar 390 × 844 pt, ale fizyczną rozdzielczość 1170 × 2532 px — dokładnie 3 razy większą, ponieważ współczynnik skali wynosi 3.
PPI (pixels per inch) — liczba pikseli przypadających na jeden cal wyświetlacza. Oblicza się według wzoru: PPI = √(szerokość² + wysokość²) / przekątna. Im wyższe PPI, tym mniejsze poszczególne piksele i tym gładszy obraz. Apple uważa za Retina wyświetlacz o PPI powyżej 300 przy typowej odległości oglądania.
Różne kategorie urządzeń mają różną gęstość: zegarki Apple Watch — 326 PPI, iPhone — 326–460 PPI, iPad — 264 PPI, MacBook Pro — 254–264 PPI. Urządzenia Android klasyfikują gęstość przez Density Buckets: mdpi (160 dpi), hdpi (240), xhdpi (320), xxhdpi (480), xxxhdpi (640). Te kubiki określają, który zasób (obraz, dimens) zostanie załadowany dla urządzenia.
Wpływ PPI na rozwój: im wyższa gęstość, tym więcej pamięci potrzeba do przechowywania tekstur i obrazów. Piksel na wyświetlaczu z 500 PPI wymaga 2.5 razy więcej pamięci GPU niż na wyświetlaczu z 320 PPI przy tym samym logicznym rozmiarze elementu. Optymalizacja zasobów pod konkretne kubiki gęstości to standardowa praktyka w programowaniu Android.
Piksele fizyczne (px) różnią się od jednostek logicznych (pt, dp, sp) tym, że są związane ze sprzętową rozdzielczością i nie skalują się. Jednostki logiczne natomiast abstrahują programistę od konkretnego wyświetlacza, pozwalając tej samej wartości 100 pt wyświetlać się z identycznym fizycznym rozmiarem na różnych urządzeniach.
| Jednostka | Platforma | Zależy od PPI | Skaluje się | Do czego |
|---|---|---|---|---|
| px | Wszystkie | Tak (piksel fizyczny) | Nie | Obrazy, bufory, Metal |
| pt | iOS/macOS | Nie (punkt logiczny) | scale factor | Layout, UIKit, SwiftUI |
| dp | Android | Nie (density-independent) | density bucket | Layout, wymiary elementów |
| sp | Android | Nie (scale-independent) | density + font scale | Tekst (textSize) |
Wzory przeliczeniowe: dla iOS — px = pt × scale (gdzie scale = 1, 2 lub 3). Dla Android — px = dp × (dpi / 160). Bezpośrednie użycie px w kodzie oznacza, że interfejs będzie wyglądał inaczej na urządzeniach o różnej gęstości: na ekranie z wysokim PPI element będzie zbyt mały, a na niskim — zbyt duży.
Używanie px w kodzie źródłowym aplikacji mobilnej — antypattern, który prowadzi do nieprawidłowego wyświetlania interfejsu na urządzeniach o różnej gęstości pikseli. Współczesne frameworki (UIKit, SwiftUI, Jetpack Compose, XML Layouts) zabraniają lub nie zalecają podawania wymiarów w pikselach.
Jedynym uzasadnionym użyciem px w kodzie jest praca z rasterami: ładowanie Bitmap, tworzenie Canvas do renderowania obrazów, praca z Metal lub OpenGL. W tych przypadkach px — fizyczne piksele docelowego bufora, które należy uwzględnić dla poprawnego renderowania. We wszystkich innych przypadkach stosuje się jednostki logiczne.
Obrazy i ikony przechowywane są w pikselach, ale dla każdego typu ekranu dostarczane są różne wersje. iOS używa sufiksów @1x, @2x, @3x w Assets.xcassets. Android używa folderów drawable-mdpi (1×), drawable-hdpi (1.5×), drawable-xhdpi (2×), drawable-xxhdpi (3×), drawable-xxxhdpi (4×). System automatycznie wybiera odpowiedni plik na podstawie gęstości ekranu.
| iOS scale | Android bucket | Współczynnik | Przykład (48 pt/dp) |
|---|---|---|---|
| @1x | mdpi (160 dpi) | 1× | 48 × 48 px |
| @2x | xhdpi (320 dpi) | 2× | 96 × 96 px |
| @3x | xxhdpi (480 dpi) | 3× | 144 × 144 px |
| — | xxxhdpi (640 dpi) | 4× | 192 × 192 px |
Zasada dostarczania zasobów: twórz obraz w formacie wektorowym (PDF, SVG) i eksportuj do kopii rastrowych o wymaganych rozmiarach. Zasoby wektorowe skalują się bez utraty jakości i zajmują mniej miejsca w repozytorium. W Android zasoby wektorowe mogą być używane bezpośrednio przez VectorDrawable, co eliminuje potrzebę wielu kopii rastrowych.
Często zadawane pytania
px — fizyczny piksel ekranu. dp (density-independent pixel) — logiczna jednostka Android, równa 1 px na ekranie o gęstości 160 dpi. Przy różnych gęstościach dp automatycznie konwertuje się na różną liczbę px, zachowując fizyczny rozmiar elementu.
Ponieważ px nie uwzględnia gęstości ekranu. Element o rozmiarze 100 px będzie wyglądał inaczej na urządzeniach z różnym PPI: na ekranie 326 PPI będzie większy niż na 460 PPI. Jednostki logiczne (dp, pt, sp) rozwiązują ten problem automatycznie.
PPI (pixels per inch) — liczba pikseli na cal wyświetlacza. Oblicza się według wzoru: PPI = √(w² + h²) / d, gdzie w i h — rozdzielczość w px, d — przekątna w calach. Im wyższe PPI, tym ostrzejszy obraz. Wyświetlacz Retina Apple zaczyna się od 300 PPI.
px jest uzasadniony przy pracy z buforami rastrowymi: tworzenie Bitmap, renderowanie w Canvas, programowanie shaderów Metal/OpenGL, przetwarzanie obrazów z kamery. W layout i typografii px nie jest używany — stosuje się pt (iOS), dp i sp (Android).
W iOS: UIScreen.main.nativeBounds zwraca rozmiar w px. W Android: DisplayMetrics.widthPixels i heightPixels z context.resources.displayMetrics. W SwiftUI: GeometryReader zwraca rozmiar w pt, dla px należy pomnożyć przez displayScale.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również