חדשות על מוצרים

מה חדש בגרסת Jetpack Compose מאוגוסט 2026

5 דקות קריאה
הצגת הפרופיל של Nick Butcher
Nick Butcher מנהל מוצר

היום, הגרסה של Jetpack Compose מאוגוסט 2026 יציבה! בגרסה הזו, גרסה 1.12 זמינה בכל מודולי הליבה של Compose (אפשר לעיין במיפוי המלא של BOM). נוספו ממשקי API ויזואליים עשירים כמו Mesh Gradients ותמיכה ב-Wide Color Gamut ‏ (WCG), תכונות פריסה מבניות כמו אזורים עם שמות ב-Grid, שילוב חלק עם Credential Manager של Android ושיפורים משמעותיים בבדיקות ובביצועים.

כדי לעדכן את הפרויקט שלך לגרסה של היום, שדרג את גרסת Compose BOM שלך ל-2026.08.00:

implementation(platform("androidx.compose:compose-bom:2026.08.00"))

שינויים פורצי דרך

  • AGP ו-Compile SDK: ‏ Compose 1.12 מעדכן את compileSdk ל-API 37, ולכן נדרשת גרסה מינימלית של AGP 9.1.2. תזכורת: תמיד מומלץ להשתמש ב-Compose עם הגרסה האחרונה של compileSdk. למידע נוסף על שינוי זה, כאן.
  • Modifier.onFirstVisible() הוצא משימוש: צריך לעבור אל Modifier.onVisibilityChanged()‎, שמאפשר מעקב מדויק יותר אחרי סף החשיפה.

גרפיקה

מעברי רשת

ב-Compose 1.12, הוספנו את MeshGradientPainter כדי לעזור לכם ליצור מעברי צבעים אורגניים עם כמה נקודות.

meshGradient.gif
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)
)

מידע נוסף ודוגמאות מופיעים במאמרי העזרה.

תמיכה בטווח צבעים רחב ו-HDR

צגים מודרניים מציעים נאמנות צבע מורחבת וטווח דינמי גבוה יותר. בגרסה Compose 1.12, תמיכה מלאה ב-Wide Color Gamut (P3) וב-Rendering HDR הופעלה בגרפיקה, צביעה ושיידרים של Compose. צבעים המוגדרים במרחבי צבע שאינם sRGB (כגון Display P3) נשמרים עד לעיבוד הפלטפורמה ללא הגבלת צבע. אם הצבעים משתמשים במרחב צבעים לא נתמך (למשל CieXyz,‏ CieLab או Oklab), אם הם מסתמכים על מרחב צבעים בגרסה לא נתמכת של Android (למשל Bt2020Hlg ב-Android 13 ומטה) או אם האפליקציה פועלת ב-Android 9 (API 28) ומטה, הצבעים יחזרו בבטחה ל-sRGB.

שינויים בולטים אחרים:

  • LayerOutsetsנוסף לGraphicsLayer וModifier.graphicsLayer, שבאמצעותו ניתן להגדיל את הגבולות החזותיים של השכבה מעבר לגודלה הנמדד. כדי למנוע את ההתנהגות המרומזת של clipToBounds כשמקדמים את השכבה למאגר מחוץ למסך, צריך להחיל LayerOutsets.

סגנונות

ב-Google I/O, שיתפנו את החזון המוקדם שלנו עבור Compose Styles API - דרך מאוחדת ויעילה לעיצוב רכיבים. מאז, המשכנו לבנות את הארכיטקטורה הבסיסית כדי להבטיח בטיחות טיפוס קפדנית ותקינות צפויה, ולתמוך בבניית מערכות עיצוב מותאמות אישית. 

כדי להבטיח שנבצע את השכבה הבסיסית הזו בצורה נכונה, ממשק ה-API יישאר ניסיוני, וניתן לצפות לשינויים משמעותיים. 

אופטימיזציות בזמן ריצה

מְקוּדָן תופעת לוואי לְהַעֲמִיס יוֹתֵר מִדַי

SideEffectכעת תומך בארגומנטים של מפתח, המאפשרים לך להפעיל אפקטים לוואי חד פעמיים בכל פעם שמפתחות ספציפיים משתנים. זה יכול להוביל לביצועים טובים יותר בהשוואה לשימוש ב-LaunchedEffect או DisposableEffect כאשר אינך זקוק לקורוטין או לבלוק הדיספוקס.SideEffect מהיר יותר בעד 90% מ-LaunchedEffect ובכ-20% מ-DisposableEffect. שימו לב ש-SideEffect פועל לפני DisposableEffect ו-LaunchedEffect, לכן צריך להיזהר אם מעבירים אפקטים קיימים ל-API הזה, במיוחד אם מדובר ב-LaunchedEffects שמסתמך על שליחה כדי להתחיל אחרי שהפריים הנוכחי מסתיים. 

@Composable
fun AnalyticsTracker(userId: String, screenName: String) {
    SideEffect(key1 = userId, key2 = screenName) {
        analytics.logScreenView(userId, screenName)
    }
}

אנימציה

מעברים אינטראקטיביים בשני שלבים

  • קומפוזיבלים חדשיםDeferredAnimatedContent וDeferredAnimatedVisibility מאפשרים יצירת מעברים דו-שלביים מקסימים, למשל למעקב חזוי אחר מחוות חזרה.
  • שליטה ידנית באנימציה: במהלך השלב הדחוי של מעבר, אפשר עכשיו לתפעל באופן ידני בזמן אמת מאפיינים של אנימציה (כמו קנה מידה או היסט) (לדוגמה, מעקב אחרי תנועת החלקה).
  • מסירה חלקה: לאחר סיום השלב הנדחה, מנוע המעבר משתלט ומבצע מסירה חלקה, כולל העברת מהירות, למעבר האוטומטי.
  • תמיכה באלמנטים משותפים חדשpermitTransformDuringDeferredTransition דגל בSharedContentConfig שולט אם אלמנטים משותפים עוברים טרנספורמציה ויזואלית יחד עם המכולות של האב שלהם במהלך שלב המעבר הנדחה.
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)
}

להלן שתי הדגמות של מקרי שימוש בהם אנימציה מונעת מחוות מועברת לאנימציה מופעלת:

colorCards.gif

שילובים של טקסט, קלט ופלטפורמות

עיצוב טקסט שניתן לערוך

ממשקי API חדשים מציעים עיצוב טקסט עשיר לטקסט שניתן לעריכה ב-BasicTextField. עכשיו אפשר להחיל ולשנות עיצוב של תווים ופסקאות בתוך השורה באופן פרוגרמטי באמצעות SpanStyle ו-ParagraphStyle דרך המתודה החדשה addStyle() בתוך היקף TextFieldBuffer (למשל בתוך textFieldState.edit { ... } או InputTransformation). בנוסף, TextFieldBuffer מספקת ממשקי API של getSpanStyles() ו-getParagraphStyles() שמחזירים אובייקטים של TrackedRange, וכך מאפשרים לקרוא, לעדכן או להסיר סגנונות שהוחלו. כדי להשלים את יצירת העיצוב, TextFieldState חושף כעת מאפיין textStyles לקריאה בלבד לשאילתות סגנונות פעילים בטווחים שונים, בעוד ש-TextFieldBuffer מספק את originalTextStyles לבדיקת מצב העיצוב לפני עריכה. עיצוב הטקסט וההערות המותאמות אישית נשמרים גם אחרי שינויים בהגדרות.

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

בחירת טקסט

חדשSelectionState API מספק שליטה תכנותית ויכולת צפייה על בחירת טקסט בתוךSelectionContainer. הרמת אובייקט של SelectionState דרך rememberSelectionState() ומעבר לתוך SelectionContainer חושפת את selectedTexts כרשימה ריאקטיבית של AnnotatedStrings ומספקת שיטות כמו selectAll(), clear(), select(TextRange) ו-extendSelectionByWord().

בנוסף, אפשר להשתמש ב-getSelectableTexts() כדי לאחזר את כל פריטי הטקסט שאפשר לבחור לפי סדר הפריסה, ולבחור טקסט ברכיבים הניתנים להרכבה ב-SelectionContainer באמצעות טווח גלובלי. 

@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.")
        }
    }
}

Credential Manager Integration

שדות הטקסט של Compose משולבים עכשיו באופן מקורי עם Credential Manager ב-Android (API 34 ומעלה) באמצעות מסגרת מילוי אוטומטי (מתחת ל-API 34, הטיפול מתבצע על ידי androidx.credentials library). על ידי צירוף מאפיין ה-semantics החדש credentialRequest עם CredentialRequestData, קלט הטקסט יכול להציג בקשות למפתחות גישה, לפרטי כניסה שמורים או לכניסה ישירות בתהליך קלט של משתמשים.

@Composable
fun LoginField(textFieldState: TextFieldState) {
    val credentialData = remember {
        CredentialRequestData(
            // Specify Credential Manager request options
        )
    }

    BasicTextField(
        state = textFieldState,
        modifier = Modifier.semantics {
            credentialRequest = credentialData
        }
    )
}

שינויים בולטים אחרים:

  • תמיכה בהגדרות וריאציות גופנים בגופנים להורדה.
  • גלילה אוטומטית מופעלת בעת גרירת בחירת טקסט מעבר לחלון התצוגה בSelectionContainer.
  • נוספה תמיכה בצלילי אינטראקציה אוטומטיים (קליקים וניווט במיקוד) לרכיבי Compose, עם קומפוזיציה חדשה SoundEffectOnInteraction שמאפשרת ביטול הסכמה. שימו לב: כתוצאה מהשינוי הזה, עכשיו צריך להפעיל את מאזיני הקליקים הסמנטיים מה-thread הראשי, וזה עשוי להשפיע על מספר קטן של תרחישי בדיקה.
  • KeyboardType כולל עכשיו את DateTimeDateTime ו-SignedDecimal.
  • BasicSecureTextFieldמשתמש כעתTextObfuscationMode.System כברירת מחדל, בעודRevealLastTyped משמש כעקיפה מוחלטת.

שיפורי פריסה

אזורים בעלי שם בפריסת רשת

בניית פריסות דו-ממדיות מורכבות קלה יותר כעת עם אזורים בעלי שם ברכיב @Experimental Grid. במקום לנהל אינדקסים מספריים של עמודות ושורות בפריטים שונים, ניתן להגדיר אזורים סמנטיים ב-GridConfigurationScope ולמקם פריטים הניתנים להרכבה לפי שם אזור.

@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"))
    }
}

למידע נוסף, עיין בתיעוד.

ביצועים

כמו בכל גרסה, אנחנו ממשיכים להשקיע בביצועים של Compose כדי לוודא שהמסגרת עוזרת לכם ליצור אפליקציות יפות ויעילות. בגרסה הזו התמקדנו בשיפור הביצועים של ההפעלה, ועכשיו אנחנו רואים זמן עד להצגה הראשונית (הזמן שנדרש לאפליקציה כדי ליצור את הפריימים הראשונים) שדומה לנתוני הצפיות במדדי ההשוואה שלנו.

timetoinitialdisplay@2x _v2.png

בדיקות ושדרוגי כלים

סינכרון בדיקה

גרסה 1.12 של Compose מציגה ממשקי API חדשים לבדיקות שנועדו להפחית את זמני ביצוע הבדיקות ולחסל אי יציבות במהלך דגימת מצבים:

  • hasPendingWork: בודקת באופן פסיבי אם יש עבודה בהמתנה בממשק המשתמש בלי להריץ את השעון, וזה אידיאלי ללולאות אנימציה ידניות.
  • runWithoutImplicitWait: השבתה זמנית של סנכרון מרומז כשמבצעים מעבר בין מסגרות זמן ידניות (למשל, בדיקות אנימציה).
@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)
            }
        }
    }
}

שינויים בולטים אחרים:

  • ה-API captureToImage מאפשר עכשיו לצלם חלון קופץ או תיבת דו-שיח יחד עם רכיב העוגן שלהם במפת סיביות אחת.
  • נוספה onRootWithViewInteraction כדי להגדיר את היקף החיפושים הסמנטיים של Compose לתצוגות ספציפיות של Android. כך אפשר לפשט את הבדיקה של ממשקי משתמש היברידיים, כמו RecyclerViews, בלי שיהיה צורך בתגי בדיקה ייחודיים בקוד הפקה.
  • @PreviewWrapperכעת ניתן להחיל הערות על יישומים מותאמים אישית@MultiPreview מחלקות, המאפשרות הגדרות תצוגה מקדימה לשימוש חוזר (כגון ערכות נושא מותאמות אישית) על פני רכיבים מרובים.

כתיבה מהנה!

Compose 1.12 הופך את פיתוח האפליקציות לקל ובעל ביטוי רב יותר מאי פעם, עם מעברי צבע של רשת, תמיכה בסולם צבעים רחב, גופנים משתנים להורדה, שילוב עם Credential Manager וכלי בדיקה מהירים יותר. כרגיל, אנו מעריכים את דעתכם, לכן אנא שתפו את המשוב שלכם על השינויים הללו או על מה שתרצו לראות בהמשך במעקב הבעיות שלנו. כתיבה מהנה!

נכתב על ידי:
המשך קריאה