Dzisiaj wersja Jetpack Compose z 26 kwietnia jest stabilna. Ta wersja zawiera wersję 1.11 podstawowych modułów Compose (zobacz pełne mapowanie BOM), narzędzia do debugowania elementów udostępnionych, zdarzenia trackpada i inne funkcje. Mamy też kilka eksperymentalnych interfejsów API, które możesz wypróbować i podzielić się z nami opinią.
Aby korzystać z dzisiejszej wersji, uaktualnij wersję Compose BOM do:
implementation(platform("androidx.compose:compose-bom:2026.04.01"))
Zmiany w Compose 1.11.0
Wykonywanie współprogramów w testach
Wprowadzamy dużą aktualizację dotyczącą sposobu, w jaki Compose obsługuje czas testów. Po okresie akceptacji ogłoszonym w Compose 1.10 interfejsy API do testowania w wersji 2 są teraz domyślne, a interfejsy API w wersji 1 zostały wycofane. Najważniejszą zmianą jest zmiana domyślnego dyspozytora testów. Interfejsy API w wersji 1 korzystały z UnconfinedTestDispatcher, który natychmiast wykonywał współprogramy, natomiast interfejsy API w wersji 2 używają StandardTestDispatcher. Oznacza to, że gdy w testach zostanie uruchomiona współprogram, zostanie ona umieszczona w kolejce i nie zostanie wykonana, dopóki zegar wirtualny nie zostanie przesunięty do przodu.
Pozwala to lepiej odtworzyć warunki produkcyjne, skutecznie eliminując sytuacje wyścigu i znacznie zwiększając stabilność i niezawodność zestawu testów.
Aby mieć pewność, że testy są zgodne ze standardowym zachowaniem współprogramów, i uniknąć problemów ze zgodnością w przyszłości, zdecydowanie zalecamy przeniesienie zestawu testów. Zapoznaj się z naszym kompleksowym przewodnikiem po migracji, aby dowiedzieć się więcej o mapowaniu interfejsów API i typowych rozwiązaniach.
Ulepszenia elementów udostępnionych i narzędzia do animacji
Dodaliśmy też kilka przydatnych narzędzi do wizualnego debugowania elementów udostępnionych i Modifier.animatedBounds. Możesz teraz dokładnie zobaczyć, co dzieje się pod maską – np. granice docelowe, trajektorie animacji i liczbę znalezionych dopasowań – co znacznie ułatwia wykrycie, dlaczego przejście może nie zachowywać się zgodnie z oczekiwaniami. Aby użyć nowego narzędzia, po prostu otocz SharedTransitionLayout elementem kompozycyjnym LookaheadAnimationVisualDebugging.
LookaheadAnimationVisualDebugging( overlayColor = Color(0x4AE91E63), isEnabled = true, multipleMatchesColor = Color.Green, isShowKeylabelEnabled = false, unmatchedElementColor = Color.Red, ) { SharedTransitionLayout { CompositionLocalProvider( LocalSharedTransitionScope provides this, ) { // your content } } }
Zdarzenia na trackpadzie
Ulepszyliśmy obsługę trackpadów w Compose, takich jak wbudowane trackpady w laptopach, dołączane trackpady do tabletów czy trackpady zewnętrzne lub wirtualne. Podstawowe zdarzenia trackpada będą teraz ogólnie traktowane jako zdarzenia PointerType.Mouse, co pozwoli dostosować działanie myszy i trackpada do oczekiwań użytkowników. Wcześniej te zdarzenia trackpada były interpretowane jako fałszywe dotknięcia ekranu dotykowego przez PointerType.Touch, co powodowało dezorientację użytkowników. Na przykład kliknięcie i przeciągnięcie za pomocą trackpada powoduje przewijanie, a nie zaznaczanie. Dzięki zmianie typu wskaźnika tych zdarzeń w najnowszej wersji Compose klikanie i przeciąganie za pomocą trackpada nie będzie już powodować przewijania.
Dodaliśmy też obsługę bardziej skomplikowanych gestów na trackpadzie, które są rozpoznawane przez platformę od interfejsu API 34, w tym przesunięć 2 palcami i uszczypnięć. Te gesty są automatycznie rozpoznawane przez komponenty takie jak Modifier.scrollable i Modifier.transformable, co zapewnia lepsze działanie trackpadów.
Te zmiany poprawiają działanie trackpadów we wbudowanych komponentach, usuwając zbędne opóźnienie dotyku, wprowadzając bardziej intuicyjny gest rozpoczynający przeciąganie i upuszczanie, zaznaczanie przez dwukrotne i trzykrotne kliknięcie w polach tekstowych oraz menu kontekstowe w polach tekstowych w stylu pulpitu.
Aby przetestować działanie trackpada, możesz użyć nowych interfejsów API do testowania z performTrackpadInput,, które umożliwiają sprawdzanie działania aplikacji podczas korzystania z trackpada. Jeśli masz niestandardowe detektory gestów, sprawdź działanie różnych typów danych wejściowych, w tym ekranów dotykowych, myszy, trackpadów i rysików, oraz upewnij się, że obsługiwane są kółka przewijania myszy i gesty na trackpadzie.
Domyślne ustawienia hosta kompozycji (środowisko wykonawcze Compose)
Wprowadziliśmy HostDefaultProvider, LocalHostDefaultProvider, HostDefaultKey i ViewTreeHostDefaultKey, aby udostępniać usługi na poziomie hosta bezpośrednio przez compose-runtime. Dzięki temu biblioteki nie muszą już polegać na compose-ui w przypadku wyszukiwania, co zapewnia lepszą obsługę Kotlin Multiplatform. Aby połączyć te wartości z drzewem kompozycji, autorzy bibliotek mogą użyć compositionLocalWithHostDefaultOf do utworzenia CompositionLocal, który rozwiązuje wartości domyślne z hosta.
Wyświetlanie podglądu kodów towarzyszących
Niestandardowe podglądy w Android Studio to nowa funkcja, która pozwala dokładnie określić, jak mają być wyświetlane treści w podglądzie Compose.
Implementując interfejs PreviewWrapperProvider i stosując nową adnotację @PreviewWrapper, możesz łatwo wstrzykiwać niestandardową logikę, np. stosować określone Theme. Adnotację można zastosować do funkcji oznaczonej adnotacją @Composable i @Preview lub @MultiPreview, co zapewnia ogólne, łatwe w użyciu rozwiązanie, które działa w przypadku funkcji w wersji testowej i znacznie zmniejsza ilość powtarzającego się kodu.
class ThemeWrapper: PreviewWrapperProvider { @Composable override fun Wrap(content: @Composable (() -> Unit)) { JetsnackTheme { content() } } } @PreviewWrapper(ThemeWrapper::class) @Preview @Composable private fun ButtonPreview() { // JetsnackTheme in effect Button(onClick = {}) { Text(text = "Demo") } }
Wycofane i usunięte funkcje
- Zgodnie z zapowiedzią w poście na blogu dotyczącym Compose 1.10 wycofujemy
Modifier.onFirstVisible(). Jego nazwa często prowadziła do nieporozumień, zwłaszcza w przypadku układów leniwych, gdzie wywoływał się wielokrotnie podczas przewijania. Zalecamy przejście naModifier.onVisibilityChanged(), co umożliwia dokładniejsze ręczne śledzenie stanów widoczności dostosowane do wymagań konkretnego przypadku użycia. - Flaga
ComposeFoundationFlags.isTextFieldDpadNavigationEnabledzostała usunięta, ponieważ nawigacja za pomocą pada kierunkowego wTextFieldsjest teraz zawsze domyślnie włączona. Nowy sposób działania zapewnia, że zdarzenia pada kierunkowego z pada do gier lub pilota do telewizora najpierw przesuwają kursor w danym kierunku. Zaznaczenie może zostać przeniesione na inny element tylko wtedy, gdy kursor dotrze do końca tekstu.
Nadchodzące interfejsy API
W nadchodzącej wersji Compose 1.12.0 compileSdk zostanie uaktualniony do compileSdk 37, a AGP 9 oraz wszystkie aplikacje i biblioteki zależne od Compose odziedziczą to wymaganie. Zalecamy aktualizowanie do najnowszych wersji, ponieważ Compose dąży do szybkiego wdrażania nowych wersji compileSdks, aby zapewnić dostęp do najnowszych funkcji Androida. Więcej informacji o tym, która wersja AGP jest obsługiwana na różnych poziomach interfejsu API, znajdziesz w dokumentacji.
W Compose 1.11.0 wprowadziliśmy te interfejsy API jako @Experimental. Chętnie poznamy Twoją opinię, gdy wypróbujesz je w swoich aplikacjach. Pamiętaj, że funkcje @Experimental APIs są udostępniane do wczesnej oceny i zbierania opinii, a w przyszłych wersjach mogą ulec znacznym zmianom lub zostać usunięte.
Style (eksperymentalne)
Wprowadzamy nowy eksperymentalny interfejs API do stylizacji. Interfejs Style API to nowy paradygmat dostosowywania elementów wizualnych komponentów, który tradycyjnie był wykonywany za pomocą modyfikatorów. Został zaprojektowany tak, aby umożliwić głębsze i łatwiejsze dostosowywanie dzięki udostępnieniu zestawu standardów właściwości, które można stylizować, z prostym stylizowaniem opartym na stanie i animowanymi przejściami. Dzięki temu nowemu interfejsowi API już teraz obserwujemy obiecujące korzyści związane z wydajnością. Planujemy zastosować style w komponentach Material, gdy interfejs Style API się ustabilizuje.
Podstawowy przykład zastępowania tła stylu stanu naciśnięcia:
@Composable fun LoginButton(modifier: Modifier = Modifier) { Button( onClick = { // Login logic }, modifier = modifier, style = { background( Brush.linearGradient( listOf(lightPurple, lightBlue) ) ) width(75.dp) height(50.dp) textAlign(TextAlign.Center) externalPadding(16.dp) pressed { background( Brush.linearGradient( listOf(Color.Magenta, Color.Red) ) ) } } ){ Text( text = "Login", ) } }
Zapoznaj się z dokumentacją i zgłoś błędy tutaj.
MediaQuery (eksperymentalne)
Nowy interfejs API mediaQuery zapewnia deklaratywny i wydajny sposób dostosowywania interfejsu do środowiska. Przekształca złożone pobieranie informacji w proste warunki w ramach UiMediaScope, dzięki czemu rekompozycja następuje tylko wtedy, gdy jest to konieczne.
Dzięki obsłudze szerokiej gamy sygnałów środowiskowych – od funkcji urządzenia, takich jak typy klawiatur i precyzja wskaźnika, po stany kontekstowe, takie jak rozmiar okna i pozycja – możesz tworzyć bardzo elastyczne rozwiązania. Wydajność jest zapewniona dzięki derivedMediaQuery, co pozwala na obsługę częstych aktualizacji, a możliwość zastępowania zakresów ułatwia testowanie i wyświetlanie podglądu w różnych konfiguracjach sprzętowych. Wcześniej, aby uzyskać dostęp do niektórych właściwości urządzenia – np. sprawdzić, czy jest ono w trybie stołu – trzeba było napisać wiele schematycznego kodu:
@Composable fun isTabletopPosture( context: Context = LocalContext.current ): Boolean { val windowLayoutInfo by WindowInfoTracker .getOrCreate(context) .windowLayoutInfo(context) .collectAsStateWithLifecycle(null) return windowLayoutInfo.displayFeatures.any { displayFeature -> displayFeature is FoldingFeature && displayFeature.state == FoldingFeature.State.HALF_OPENED && displayFeature.orientation == FoldingFeature.Orientation.HORIZONTAL } } @Composable fun VideoPlayer() { if(isTabletopPosture()) { TabletopLayout() } else { FlatLayout() } }
Teraz dzięki UIMediaQuery możesz dodać składnię mediaQuery, aby wysyłać zapytania o właściwości urządzenia, np. czy jest ono w trybie stołu:
@OptIn(ExperimentalMediaQueryApi::class) @Composable fun VideoPlayer() { if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) { TabletopLayout() } else { FlatLayout() } }
Zapoznaj się z dokumentacją i zgłoś błędy tutaj.
Siatka (eksperymentalna)
Grid to nowy, zaawansowany interfejs API do tworzenia złożonych, dwuwymiarowych układów w Jetpack Compose. Row i Column świetnie nadają się do projektów liniowych, ale Grid zapewnia kontrolę strukturalną potrzebną w przypadku architektury na poziomie ekranu i skomplikowanych komponentów bez obciążenia związanego z przewijaną listą. Grid umożliwia definiowanie układu za pomocą ścieżek, odstępów i komórek, oferując znane opcje rozmiaru, takie jak Dp, wartości procentowe, rozmiary treści wewnętrznych i elastyczne jednostki „Fr”.
@OptIn(ExperimentalGridApi::class) @Composable fun GridExample() { Grid( config = { repeat(4) { column(0.25f) } repeat(2) { row(0.5f) } gap(16.dp) } ) { Card1(modifier = Modifier.gridItem(rowSpan = 2) Card2(modifier = Modifier.gridItem(colmnSpan = 3) Card3(modifier = Modifier.gridItem(columnSpan = 2) Card4() } }
Możesz umieszczać elementy automatycznie lub precyzyjnie rozciągać je na wiele wierszy i kolumn. Co najważniejsze, jest on bardzo elastyczny – możesz dynamicznie zmieniać konfigurację ścieżek i rozpiętości siatki, aby reagować na stany urządzenia, takie jak tryb stołu czy zmiany orientacji, dzięki czemu interfejs użytkownika będzie wyglądał świetnie na różnych formatach.
Zapoznaj się z dokumentacją i zgłoś błędy tutaj.
FlexBox (eksperymentalny)
FlexBox to kontener układu zaprojektowany z myślą o wysokiej wydajności i adaptacyjnych interfejsach użytkownika. Zarządza rozmiarem elementów i rozkładem przestrzeni na podstawie dostępnych wymiarów kontenera. Obsługuje złożone zadania, takie jak zawijanie (wrap) i wyrównywanie elementów względem wielu osi (justifyContent, alignItems, alignContent). Umożliwia powiększanie (grow) lub zmniejszanie (shrink) elementów w celu wypełnienia kontenera.
@OptIn(ExperimentalFlexBoxApi::class) fun FlexBoxWrapping(){ FlexBox( config = { wrap(FlexWrap.Wrap) gap(8.dp) } ) { RedRoundedBox() BlueRoundedBox() GreenRoundedBox(modifier = Modifier.width(350.dp).flex { grow(1.0f) }) OrangeRoundedBox(modifier = Modifier.width(200.dp).flex { grow(0.7f) }) PinkRoundedBox(modifier = Modifier.width(200.dp).flex { grow(0.3f) }) } }
Zapoznaj się z dokumentacją i zgłoś błędy tutaj.
Nowa implementacja SlotTable (funkcja eksperymentalna)
Wprowadziliśmy nową implementację SlotTable, która jest domyślnie wyłączona w tej wersji. SlotTable to wewnętrzna struktura danych, której środowisko wykonawcze Compose używa do śledzenia stanu hierarchii kompozycji, śledzenia unieważnień i rekompozycji, przechowywania zapamiętanych wartości oraz śledzenia wszystkich metadanych kompozycji w czasie działania. Ta nowa implementacja ma na celu poprawę wydajności, przede wszystkim w przypadku losowych zmian.
Aby wypróbować nową wersję SlotTable, włącz ComposeRuntimeFlags.isLinkBufferComposerEnabled.
Zacznij kodować już dziś.
W Jetpack Compose jest już dostępnych wiele nowych, ciekawych interfejsów API, a wkrótce pojawi się ich jeszcze więcej. To najlepszy moment, aby przejść na Jetpack Compose. Jak zawsze będziemy wdzięczni za opinie i prośby o dodanie funkcji (zwłaszcza tych, które są jeszcze w fazie @Experimental). Możesz je przesłać tutaj. Powodzenia!
-
Wiadomości o usłudzeDzisiaj, podczas Android Dev Summit, ogłaszamy szeroką dostępność wielu narzędzi i interfejsów API, które mają na celu usunięcie codziennych problemów i zapewnienie większej elastyczności podczas tworzenia świetnych aplikacji na Androida.
Matthew McCullough • Czas czytania: 4 min -
Wiadomości o usłudzeAndroid Studio Rabbit 2 jest teraz stabilny i gotowy do użycia w środowisku produkcyjnym. Ta wersja zawiera kluczowe funkcje, które ułatwią Ci programowanie, takie jak Bring Your Own Agent, nowe funkcje emulatora XR, aktualizacja LeakCanary, nowe narzędzie do zarządzania umiejętnościami agenta, inspekcja kodu przez AI i inne.
Matthew Warner • Czas czytania: 3 min -
Wiadomości o usłudzeAplikacje kierowane na nadchodzącą wersję Androida nie będą już mogły bezpośrednio zapisywać kontaktów za pomocą uprawnienia WRITE_CONTACTS.
Roxanna Aliabadi Walker • Czas czytania: 6 min
Otrzymuj co tydzień najnowsze informacje o tworzeniu aplikacji na Androida na swoją skrzynkę odbiorczą.