Dziś ogłaszamy, że wersja Jetpack Compose z sierpnia 2026 r. jest stabilna. Ta wersja zawiera wersję 1.12 w podstawowych modułach Compose (pełne mapowanie BOM), wprowadza bogate wizualne interfejsy API, takie jak gradienty siatkowe i obsługa szerokiej gamy kolorów (WCG), funkcje układu strukturalnego, takie jak nazwane obszary w Grid, bezproblemową integrację z Credential Managerem Androida oraz znaczące ulepszenia testowania i wydajności.
Aby zaktualizować projekt do dzisiejszej wersji, uaktualnij wersję Compose BOM do 2026.08.00:
implementation(platform("androidx.compose:compose-bom:2026.08.00"))
Zmiany powodujące niezgodność
- AGP i pakiet SDK do kompilacji: Compose 1.12 aktualizuje compileSdk do API 37, co wymaga co najmniej AGP 9.1.2. Przypominamy, że Compose zawsze będzie kierować się najnowszym compileSdk. Więcej informacji o tej zmianie znajdziesz tutaj.
Modifier.onFirstVisible()został wycofany: przejdź na Modifier.onVisibilityChanged(), który zapewnia dokładniejsze śledzenie progu widoczności.
Grafika
Gradienty siatkowe
Compose 1.12 wprowadza MeshGradientPainter, który pomaga tworzyć wielopunktowe, organiczne gradienty kolorów.
val rows = 1 val columns = 1 val gradientPainter = remember { MeshGradientPainter(rows, columns) { // Parameters: row, column, position, color setVertex(0, 0, Offset(0f, 0f), Color.Red) // Top-Left setVertex(0, 1, Offset(1f, 0f), Color.Blue) // Top-Right setVertex(1, 0, Offset(0f, 1f), Color.Green) // Bottom-Left setVertex(1, 1, Offset(1f, 1f), Color.Yellow) // Bottom-Right } } Box( modifier = modifier .aspectRatio(16/9f) .fillMaxWidth() .paint(gradientPainter) )
Więcej informacji i przykłady znajdziesz w dokumentacji.
Obsługa szerokiej gamy kolorów i HDR
Nowoczesne wyświetlacze oferują rozszerzoną wierność kolorów i większy zakres dynamiczny. W Compose 1.12 włączono pełną obsługę szerokiej gamy kolorów (P3) i renderowania HDR w grafice, malowaniu i shaderach Compose. Kolory zdefiniowane w przestrzeniach kolorów innych niż sRGB (np. Display P3) są zachowywane podczas renderowania na platformie bez przycinania kolorów. Jeśli kolory używają nieobsługiwanej przestrzeni kolorów (np. CieXyz, CieLab lub Oklab), opierają się na przestrzeni kolorów w nieobsługiwanej wersji Androida (np. Bt2020Hlg w Androidzie 13 i starszych) lub jeśli aplikacja działa w Androidzie 9 (API 28) i starszych, bezpiecznie powrócą do sRGB.
Inne ważne zmiany:
LayerOutsetsdodano doGraphicsLayeriModifier.graphicsLayer, którego można użyć do zwiększenia wizualnych granic warstwy poza jej zmierzony rozmiar. ZastosujLayerOutsets, aby uniknąć domyślnego zachowaniaclipToBounds, gdy warstwa jest promowana do bufora poza ekranem.
Style
Podczas Google I/O przedstawiliśmy naszą wstępną wizję interfejsu Styles API w Compose – ujednoliconego i wydajnego sposobu stylizowania komponentów. Od tego czasu kontynuowaliśmy budowanie podstawowej architektury, aby zagwarantować ścisłe zabezpieczenia wpisywania i przewidywalną poprawność oraz obsługę tworzenia niestandardowych systemów projektowania.
Aby mieć pewność, że ta podstawowa warstwa jest prawidłowa, interfejs API pozostanie eksperymentalny i możesz spodziewać się zmian powodujących niezgodność.
Optymalizacje czasu działania
Przeciążenie SideEffect z kluczem
SideEffect obsługuje teraz argumenty klucza, co pozwala wywoływać jednorazowe efekty uboczne, gdy zmieniają się określone klucze. Może to prowadzić do lepszej wydajności w porównaniu z używaniem LaunchedEffect lub DisposableEffect gdy nie potrzebujesz współprogramu ani bloku dispose. SideEffect jest nawet o 90% szybszy niż LaunchedEffect i o około 20% szybszy niż DisposableEffect. Pamiętaj, że SideEffect uruchamia swój efekt przed DisposableEffect i LaunchedEffect, więc zachowaj ostrożność podczas przenoszenia istniejących efektów do tego interfejsu API, zwłaszcza w przypadku LaunchedEffects, które mają być wysyłane po zakończeniu bieżącej klatki.
@Composable fun AnalyticsTracker(userId: String, screenName: String) { SideEffect(key1 = userId, key2 = screenName) { analytics.logScreenView(userId, screenName) } }
Animacje
DeferredTargetAnimationwyszedł ze stanu eksperymentalnego.
Interaktywne przejścia dwuetapowe
- Nowe elementy kompozycyjne:
DeferredAnimatedContentiDeferredAnimatedVisibilityumożliwiają tworzenie atrakcyjnych przejść dwuetapowych, np. do śledzenia gestu przewidywanego przejścia wstecz. - Ręczne sterowanie animacją: podczas odroczonej fazy przejścia właściwości animowane (np.skala lub przesunięcie) można teraz ręcznie manipulować w czasie rzeczywistym (np. śledząc gest przesuwania).
- Bezproblemowe przekazywanie: po zakończeniu odroczonej fazy przejścia przejmuje silnik przejścia i wykonuje bezproblemowe przekazanie, w tym transfer prędkości, do przejścia automatycznego.
- Obsługa elementów wspólnych: nowa flaga
permitTransformDuringDeferredTransitionwSharedContentConfigokreśla, czy elementy wspólne mają się wizualnie przekształcać wraz z kontenerami nadrzędnymi podczas odroczonej fazy przejścia.
val state = remember { DeferredTransitionState(initialScreen) } val transition = rememberDeferredTransition(state) if (predictiveBackInProgress) { state.defer(targetScreen) } else { state.animateTo(targetScreen) } transition.DeferredAnimatedContent( targetState = targetScreen, mutableTransformSpec = { MutableContentTransform { // Manually manipulate properties during the deferred phase initialContentTransform { scale = swipeProgress } } } ) { screen -> ScreenContent(screen) }
Poniżej znajdziesz 2 prezentacje przypadków użycia, w których animacja sterowana gestem jest przekazywana do animacji wyzwalanej:
Integracje tekstu, danych wejściowych i platformy
Formatowanie edytowalnego tekstu
Nowe interfejsy API oferują formatowanie tekstu sformatowanego w edytowalnym tekście w BasicTextField. Możesz teraz programowo stosować i manipulować formatowaniem znaków i akapitów w tekście za pomocą SpanStyle i ParagraphStyle za pomocą nowej metody addStyle() w zakresie TextFieldBuffer (np. w textFieldState.edit { ... } lub InputTransformation). Dodatkowo TextFieldBuffer udostępnia interfejsy API getSpanStyles() i getParagraphStyles(), które zwracają obiekty TrackedRange, co umożliwia odczytywanie, aktualizowanie i usuwanie zastosowanych stylów. Aby uzupełnić tworzenie formatowania, TextFieldState udostępnia teraz właściwość textStyles tylko do odczytu, która umożliwia wysyłanie zapytań o aktywne style w zakresach, a TextFieldBuffer udostępnia originalTextStyles do sprawdzania stanu formatowania przed edycją. Formatowanie tekstu i niestandardowe adnotacje są zachowywane po zmianach konfiguracji.
val state = rememberTextFieldState("Formatted text in Compose 1.12") // Apply bold and color styles to a range of text state.edit { addStyle( SpanStyle(fontWeight = FontWeight.Bold, color = Color.Blue), start = 0, end = 9 ) } // Query active styles from TextFieldState val currentStyles = state.textStyles
Zaznaczanie tekstu
Nowy interfejs API SelectionState zapewnia zautomatyzowane sterowanie i dostrzegalność zaznaczenia tekstu w SelectionContainer. Przeniesienie obiektu SelectionState za pomocą rememberSelectionState() i przekazanie go do SelectionContainer udostępnia selectedTexts jako reaktywną listę AnnotatedStrings oraz metody takie jak selectAll(), clear(), select(TextRange) i extendSelectionByWord().
Dodatkowo użyj getSelectableTexts(), aby pobrać wszystkie elementy tekstowe, które można zaznaczyć, w kolejności układu i zaznaczyć tekst w elementach kompozycyjnych w SelectionContainer za pomocą zakresu globalnego.
@Composable fun ProgrammaticSelectionExample() { val selectionState = rememberSelectionState() Column { Button( onClick = { selectionState.selectAll() }, modifier = Modifier.disableSelectionClearOnTap() ) { Text("Select All") } SelectionContainer(state = selectionState) { Text("Text content to be selected programmatically.") } } }
Integracja z Credential Managerem
Pola tekstowe Compose są teraz natywnie zintegrowane z Credential Managerem Androida (API 34+) za pomocą platformy Autofill (w przypadku API poniżej 34 obsługuje je androidx.credentials library). Dzięki dołączeniu nowej właściwości semantycznej credentialRequest z CredentialRequestData, pola tekstowe mogą wyświetlać prośby o klucze dostępu, zapisane dane logowania lub logowanie bezpośrednio w procesie wprowadzania danych przez użytkownika.
@Composable fun LoginField(textFieldState: TextFieldState) { val credentialData = remember { CredentialRequestData( // Specify Credential Manager request options ) } BasicTextField( state = textFieldState, modifier = Modifier.semantics { credentialRequest = credentialData } ) }
Inne ważne zmiany:
- Obsługa ustawień wariantów czcionek w czcionkach do pobrania.
- Włączono automatyczne przewijanie podczas przeciągania zaznaczenia tekstu poza obszar widoczny w
SelectionContainer. - Dodano obsługę automatycznych dźwięków interakcji (kliknięć i nawigacji za pomocą fokusu) w komponentach Compose, a także nowy element kompozycyjny
SoundEffectOnInteraction, który umożliwia rezygnację. Pamiętaj, że w wyniku tej zmiany detektory kliknięć semantycznych muszą być teraz wywoływane z wątku głównego, co może wpłynąć na niewielką liczbę przypadków testowych. KeyboardTypezawiera terazDate,Time,DateTime, iSignedDecimal.BasicSecureTextFielddomyślnie używa terazTextObfuscationMode.System, aRevealLastTypedsłuży jako bezwzględne zastąpienie.
Ulepszenia układu
Nazwane obszary w układzie siatki
Tworzenie złożonych układów 2D jest teraz łatwiejsze dzięki nazwom obszarów w komponencie @Experimental Grid. Zamiast zarządzać numerycznymi indeksami kolumn i wierszy w elementach, możesz zdefiniować regiony semantyczne w GridConfigurationScope i umieszczać elementy kompozycyjne według nazwy obszaru.
@OptIn(ExperimentalGridApi::class) @Composable fun DashboardLayout() { Grid( config = { area("header", row = 0, column = 0, rowSpan = 1, columnSpan = 2) area("sidebar", row = 1, column = 0) area("content", row = 1, column = 1) gap(16.dp) } ) { HeaderSection(modifier = Modifier.gridItem(areaId = "header")) NavigationSidebar(modifier = Modifier.gridItem(areaId = "sidebar")) MainContentView(modifier = Modifier.gridItem(areaId = "content")) } }
Więcej informacji znajdziesz w dokumentacji.
Wydajność
Jak w przypadku każdej wersji, nadal inwestujemy w wydajność Compose, aby mieć pewność, że platforma pomoże Ci tworzyć piękne i wydajne aplikacje. W tej wersji skupiliśmy się na poprawie wydajności uruchamiania i widzimy teraz czas do pierwszego wyświetlenia (czas potrzebny aplikacji na wygenerowanie pierwszej klatki) porównywalny z widokami w naszych testach porównawczych.
Ulepszenia testowania i narzędzi
Synchronizacja testów
Compose 1.12 wprowadza nowe interfejsy API testów, które mają na celu skrócenie czasu wykonywania testów i wyeliminowanie niestabilności podczas próbkowania stanu:
hasPendingWork: pasywnie sprawdza, czy interfejs użytkownika ma oczekujące zadania, bez przesuwania zegara, co jest idealne w przypadku ręcznych pętli animacji.runWithoutImplicitWait: tymczasowo wyłącza synchronizację niejawną podczas przechodzenia przez klatki zegara ręcznego (np. testy animacji).
@Test fun testAnimationStateFast() { composeTestRule.mainClock.autoAdvance = false while (composeTestRule.hasPendingWork()) { composeTestRule.mainClock.advanceTimeByFrame() composeTestRule.waitForIdle() composeTestRule.runOnUiThread { composeTestRule.runWithoutImplicitWait { // This is most effective when querying multiple nodes in a single frame. // It prevents the redundant synchronization overhead that would // otherwise occur on every individual query. val box1 = composeTestRule.onNodeWithTag("Box1").fetchSemanticsNode() val box2 = composeTestRule.onNodeWithTag("Box2").fetchSemanticsNode() assertThat(box1.boundsInRoot.right).isAtMost(box2.boundsInRoot.left) } } } }
Inne ważne zmiany:
- Interfejs API
captureToImageumożliwia teraz przechwytywanie wyskakującego okienka lub okna dialogowego wraz z jego kotwicą w jednej bitmapie. - Dodano
onRootWithViewInteraction, aby ograniczyć wyszukiwanie semantyczne Compose do określonych widoków Androida. Upraszcza to testowanie hybrydowych interfejsów użytkownika, takich jakRecyclerViews, bez konieczności używania unikalnych tagów testowych w kodzie produkcyjnym. @PreviewWrapperadnotacje można teraz stosować do niestandardowych@MultiPreviewklas, co umożliwia ponowne wykorzystywanie konfiguracji podglądu (np. motywów niestandardowych) w wielu komponentach.
Miłego tworzenia w Compose!
Compose 1.12 ułatwia i przyspiesza tworzenie aplikacji dzięki gradientom siatkowym, obsłudze szerokiej gamy kolorów, czcionkom zmiennym do pobrania, integracji z Credential Managerem i szybszym narzędziom do testowania. Jak zawsze cenimy Twoją opinię, więc podziel się nią na temat tych zmian lub tego, co chcesz zobaczyć w przyszłości, w naszym systemie śledzenia problemów. Miłego tworzenia w Compose!
-
Wiadomości o usługachWraz z wprowadzeniem Pixela 11 Pro Fold, Pixela Watch 5 i całej rodziny Pixeli użytkownicy mogą płynnie przechodzić między różnymi rozmiarami ekranów, unikalnymi pozycjami i inteligentnymi funkcjami.
Fahd Imtiaz, Loryn Hairston, Tracy Agyemang • Czas czytania: 4 minuty -
Wiadomości o usługachDziś oficjalnie obchodzimy 5. rocznicę wydania Jetpack Compose 1.0. Od wersji 1.0, ogłoszonej 28 lipca 2021 r., do najnowszej wersji 1.11 interfejsy API znacznie się rozwinęły, dlatego chcemy to uczcić.
Rebecca Franks, Nick Butcher, Loryn Hairston • Czas czytania: 4 minuty -
Wiadomości o usługachW ciągu prawie 5 lat od wprowadzenia Jetpack Compose zainwestowaliśmy w udostępnienie Ci wszystkich funkcji, wydajności i narzędzi potrzebnych do tworzenia niesamowitych interfejsów użytkownika na różnych urządzeniach z Androidem.
Nick Butcher • Czas czytania: 2 minuty
Otrzymuj co tydzień najnowsze informacje o tworzeniu aplikacji na Androida na swoją skrzynkę odbiorczą.