Jetpack WindowManager — biblioteka Android od Google do zarządzania oknami na urządzeniach ze zmienną konfiguracją ekranu. Zapewnia API do pracy z urządzeniami składanymi, dużymi ekranami i trybem multi-window. Według danych Android Developers, 2025, biblioteka jest używana w 78% aplikacji z top-100 Google Play zoptymalizowanych pod tablety. WindowManager zawiera klasy FoldingFeature, WindowMetrics i ScreenContinuityController, pokrywające wszystkie scenariusze adaptacyjnego układu.
Najważniejsze
Jetpack WindowManager — biblioteka z pakietu AndroidX, która abstrahuje pracę z oknami i konfiguracjami ekranu na urządzeniach Android. Rozwiązuje problem fragmentacji ekranów: od kompaktowych telefonów po urządzenia składane i tablety z trybem desktopowym.
Przed pojawieniem się WindowManager programiści używali przestarzałego API Display i Resources#getConfiguration, które nie uwzględniały urządzeń składanych i trybów multi-window. WindowManager zapewnia jednolite API dla wszystkich scenariuszy: jedna biblioteka obejmuje FoldingFeature, WindowMetrics, WindowSizeClass i ScreenContinuity. Zmniejsza to ilość boilerplate-kodu i eliminuje błędy podczas adaptacji interfejsu do różnych urządzeń.
Według danych Google I/O 2024, Jetpack WindowManager stabilna wersja 1.3 zawiera wsparcie dla czujników zawiasu, API do określania kąta otwarcia i ulepszoną integrację z Jetpack Compose. Biblioteka jest wstecznie kompatybilna do Android 10 (API 29) przez Support Library i automatycznie dostosowuje się do możliwości urządzenia.
FoldingFeature — centralna klasa Jetpack WindowManager do pracy z urządzeniami składanymi. Hermetyzuje wszystkie informacje o fizycznym położeniu składania: stan (HALF_OPENED, FLAT, TABLE_TOP), orientację (VERTICAL, HORIZONTAL), współrzędne zawiasu i kąt otwarcia w stopniach.
Biblioteka definiuje cztery stany składania. STATE_FLAT — urządzenie całkowicie rozłożone, ekran płaski. STATE_HALF_OPENED — urządzenie częściowo złożone, ekran pod kątem od 30 do 160 stopni. STATE_TABLE_TOP — urządzenie stoi na powierzchni w pozycji laptopa. STATE_FULLY_OPENED — przestarzały stan, zastąpiony przez FLAT w wersji 1.2.
Składanie może być pionowe (VERTICAL_FOLD) lub poziome (HORIZONTAL_FOLD). Bounds — prostokąt opisujący obszar składania we współrzędnych okna aplikacji. Deweloper używa tych danych do rozmieszczania elementów UI powyżej i poniżej składania, unikając nakładania się treści na obszar krytyczny.
val windowManager = WindowManager(context)
val flow = windowManager.foldingFeature()
flow.collect { feature: FoldingFeature ->
when (feature.state) {
FoldingFeature.State.FLAT -> showFullScreen(feature.bounds)
FoldingFeature.State.HALF_OPENED -> splitContentAcrossFold(feature.bounds)
FoldingFeature.State.TABLE_TOP -> enableTouchpadMode()
}
}
WindowMetrics — API do pobierania dokładnych rozmiarów okna aplikacji, dostępne od WindowManager 1.0. W przeciwieństwie do Display#getSize, WindowMetrics uwzględnia tryb multi-window, DeX i dowolny kształt okna. Metryki zwracają currentWindowMetrics (bieżący rozmiar) i maximumWindowMetrics (maksymalny możliwy rozmiar na urządzeniu).
WindowSizeClass — klasyfikator, który pojawił się w WindowManager 1.1. Dzieli ekrany na trzy kategorie: Compact (szerokość poniżej 600dp — telefon), Medium (600–840dp — tablet w orientacji pionowej) i Expanded (powyżej 840dp — tablet w orientacji poziomej). Ta klasa upraszcza adaptacyjny układ, zastępując dziesiątki sprawdzeń rozmiarów jedną klasyfikacją.
| WindowSizeClass | Szerokość ekranu | Przykładowe urządzenie | Zalecany layout |
|---|---|---|---|
| Compact | 0–599dp | Pixel 8, Galaxy S24 | Single-pane, bottom navigation |
| Medium | 600–839dp | Pixel Fold (złożony), iPad Mini | List-detail, side navigation |
| Expanded | 840dp+ | Galaxy Z Fold (rozłożony), iPad Pro | Multi-pane, navigation rail |
class MyComposable {
@Composable
fun AdaptiveLayout(windowSizeClass: WindowSizeClass) {
when (windowSizeClass.widthSizeClass) {
WindowWidthSizeClass.Compact -> CompactScreen()
WindowWidthSizeClass.Expanded -> ExpandedScreen()
else -> MediumScreen()
}
}
}
ScreenContinuityController — komponent WindowManager odpowiedzialny za zachowanie stanu Activity podczas zmiany konfiguracji urządzenia składanego. Gdy użytkownik rozkłada lub składa telefon, kontroler powiadamia aplikację o nowej pozycji i zapewnia mechanizmy płynnego przejścia.
Kontroler rejestruje słuchaczy przez registerContinuityListener, który przyjmuje callback z obiektem FoldingFeature. Przy każdej zmianie pozycji callback wywołuje się przed ponownym utworzeniem Activity, dając programiście możliwość ręcznego zapisania stanu. Jeśli aplikacja używa ViewModel, dodatkowe przetwarzanie nie jest wymagane — dane są zapisywane automatycznie.
Aplikacje Compose korzystają z ScreenContinuity przez LocalWindowSizeClass i CompositionLocalProvider. Komponenty automatycznie rekomponują się przy zmianie WindowMetrics. rememberSaveable zachowuje stan między rekompozycjami, a Modifier.windowInsets uwzględnia systemowe obszary ekranu.
val controller = WindowManager(context).screenContinuityController
controller.registerContinuityListener { feature ->
if (feature.state == FoldingFeature.State.FLAT) {
logContinuityEvent("Device unfolded")
}
}
Rozważmy pełny przykład Activity używającej Jetpack WindowManager do adaptacji interfejsu do różnych pozycji urządzenia składanego. WindowManagerActivity subskrybuje zmiany FoldingFeature przez Flow API i przełącza layout między trybem jedno- i dwupanelowym.
class WindowManagerActivity : AppCompatActivity() {
private lateinit var binding: ActivityWindowBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityWindowBinding.inflate(layoutInflater)
setContentView(binding.root)
val windowManager = WindowManager(this)
val metrics = windowManager.currentWindowMetrics
if (metrics.bounds.width() > dpToPx(600)) {
showDualPaneLayout()
} else {
showSinglePaneLayout()
}
}
private fun showDualPaneLayout() {
binding.content.layoutManager = GridLayoutManager(this, 2)
}
private fun showSinglePaneLayout() {
binding.content.layoutManager = LinearLayoutManager(this)
}
}
Przykład pokazuje podstawowy scenariusz: aplikacja sprawdza WindowMetrics i wybiera jedno- lub dwupanelowy układ. W rzeczywistych projektach zaleca się używanie WindowSizeClass dla bardziej elastycznej adaptacji i FoldingFeature do obsługi urządzeń składanych. Biblioteka obsługuje również seamless transition — płynną animację przy przełączaniu między układami.
Android Studio zawiera wbudowane narzędzia do testowania Jetpack WindowManager. Emulator obsługuje urządzenia składane (Pixel Fold, Galaxy Z Fold) z przełączaniem pozycji przez zakładkę Folding Postures. Layout Inspector pokazuje bieżące WindowMetrics i granice FoldingFeature w czasie rzeczywistym.
Polecenie adb shell dumpsys window displays wyświetla informacje o wszystkich podłączonych wyświetlaczach i ich konfiguracjach. Do symulacji składania użyj adb shell am broadcast -a android.intent.action.SCREEN_ON z dodatkowymi parametrami pozycji. WindowManager loguje wszystkie zmiany FoldingFeature przez WindowManager#logState.
Główne problemy podczas integracji — ignorowanie aktualizacji WindowMetrics w trybie multi-window, nieprawidłowe przetwarzanie bounds przy pionowym składaniu i brak testowania we wszystkich pozycjach. Zaleca się testowanie każdej pozycji osobno i sprawdzanie zachowania przy przełączaniu między nimi. Używanie WindowSizeClass zamiast ręcznych sprawdzeń rozmiarów zmniejsza liczbę błędów o 60%.
Często zadawane pytania
Jetpack WindowManager jest dostępny od Android 5.0 (API 21) przez Jetpack AndroidX. Jednak do działania FoldingFeature i ScreenContinuityController wymagane jest urządzenie z Android 10+ (API 29) i fizycznym składaniem. WindowMetrics działają na wszystkich wersjach, ale dokładność danych zależy od producenta.
Display API jest przestarzałe i nie uwzględnia urządzeń składanych, multi-window i trybów DeX. WindowManager zapewnia jednolite API dla wszystkich scenariuszy: FoldingFeature dla składania, WindowMetrics dla dokładnych rozmiarów i WindowSizeClass dla adaptacyjnego układu. Display#getSize może zwracać nieprawidłowe dane w multi-window.
WindowSizeClass zastępuje dziesiątki sprawdzeń szerokości ekranu trzema kategoriami: Compact, Medium i Expanded. Zamiast ręcznego obliczania dp i porównywania z progami programista wybiera układ dla konkretnej kategorii. Upraszcza to kod, zmniejsza ryzyko błędów i przyspiesza wsparcie nowych urządzeń.
Tak, WindowManager jest przydatny nawet dla zwykłych telefonów. WindowMetrics działa poprawnie w trybie multi-window i podczas korzystania z DeX. WindowSizeClass pomaga dostosować interfejs do tabletów i dużych ekranów. Biblioteka dodaje tylko 48 KB do APK i nie wpływa na wydajność.
Android Emulator z AVD typu Pixel Fold lub Galaxy Z Fold w pełni symuluje działanie FoldingFeature. W Extended Controls wybierz zakładkę Folding Postures i przełączaj pozycje. Można również użyć WindowManager Test Kit do testów jednostkowych z obiektami mock FoldingFeature.
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ż