أخبار المنتجات

الميزات الجديدة في إصدار Jetpack Compose لشهر أغسطس 2026

مدّة القراءة: 5 دقائق
عرض الملف الشخصي لـ Nick Butcher
Nick Butcher مدير منتجات

أصبح إصدار أغسطس 2026 من Jetpack Compose ثابتًا اليوم. يتضمّن هذا الإصدار الإصدار 1.12 في جميع وحدات Compose الأساسية (راجِع خريطة BOM الكاملة)، ويقدّم واجهات برمجة تطبيقات مرئية غنية، مثل Mesh Gradients وإمكانية استخدام مجموعة ألوان واسعة (WCG)، وميزات التنسيق البنيوي، مثل المناطق المسماة في Grid، والتكامل السلس مع "مدير بيانات الاعتماد" في Android، وتحسينات كبيرة في الاختبار والأداء.

لتحديث مشروعك إلى الإصدار الحالي، عليك ترقية إصدار Compose BOM إلى 2026.08.00:

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

التغييرات التي قد تؤدي إلى أعطال

  • مكوّن Android الإضافي (AGP) وحزمة تطوير البرامج (SDK) للتجميع: يحدّث الإصدار 1.12 من Compose حزمة تطوير البرامج (SDK) للتجميع إلى الإصدار 37 من واجهة برمجة التطبيقات، ما يتطلّب توفّر الإصدار 9.1.2 من مكوّن Android الإضافي (AGP) كحد أدنى. للتذكير، سيستهدف Compose دائمًا أحدث إصدار من compileSdk. مزيد من المعلومات حول هذا التغيير
  • تم إيقاف Modifier.onFirstVisible() نهائيًا: يُرجى الانتقال إلى Modifier.onVisibilityChanged()‎، الذي يوفّر تتبُّعًا أكثر دقة لحدّ الظهور.

الرسومات

التدرّجات الشبكية

يقدّم الإصدار 1.12 من Compose 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

توفّر الشاشات الحديثة دقة ألوان محسّنة ونطاقًا ديناميكيًا أعلى. في الإصدار 1.12 من Compose، تم تفعيل إمكانية استخدام مسار التعلّم الكامل لنطاق الألوان الواسع (P3) وعرض نطاق عالي الديناميكية في جميع رسومات Compose وألوانها وأدوات تظليلها. يتم الاحتفاظ بالألوان المحدّدة في مساحات الألوان غير sRGB (مثل Display P3) إلى أن يتم عرضها على المنصة بدون حصر الألوان. سيتم الرجوع إلى ألوان sRGB بأمان إذا كانت تستخدم مساحة ألوان غير متوافقة (مثل CieXyz أو CieLab أو Oklab)، أو تعتمد على مساحة ألوان في إصدار غير متوافق من Android (مثل Bt2020Hlg على Android 13 والإصدارات الأقدم)، أو إذا كان التطبيق يعمل على الإصدار 9 من نظام التشغيل Android (المستوى 28 من واجهة برمجة التطبيقات) والإصدارات الأقدم.

التغييرات البارزة الأخرى:

  • تمت إضافة LayerOutsets إلى GraphicsLayer وModifier.graphicsLayer، ويمكنك استخدامها لزيادة الحدود المرئية للطبقة إلى ما يتجاوز حجمها المقاس. طبِّق LayerOutsets لتجنُّب السلوك الضمني clipToBounds عند ترقية الطبقة إلى مخزن مؤقت خارج الشاشة.

الأنماط

في مؤتمر Google I/O، شاركنا رؤيتنا الأولية بشأن Styles API في Compose، وهي طريقة موحّدة وفعّالة لتصميم المكوّنات. ومنذ ذلك الحين، واصلنا تطوير البنية الأساسية لضمان أمان الأنواع بشكل صارم وصحة النتائج المتوقّعة، ولإتاحة إنشاء أنظمة تصميم مخصّصة. 

لضمان صحة هذه الطبقة الأساسية، ستظل واجهة برمجة التطبيقات تجريبية، ويمكنك توقّع تغييرات غير متوافقة مع الإصدارات السابقة. 

تحسينات وقت التشغيل

Keyed SideEffect Overload

تتيح السمة SideEffect الآن استخدام وسيطات رئيسية، ما يتيح لك تشغيل تأثيرات جانبية لمرة واحدة كلما تغيّرت مفاتيح معيّنة. يمكن أن يؤدي ذلك إلى تحسين الأداء مقارنةً باستخدام LaunchedEffect أو DisposableEffect عندما لا تحتاج إلى الروتين الفرعي أو كتلة الإلغاء. SideEffect أسرع بنسبة تصل إلى ‎90% من LaunchedEffect وأسرع بنسبة ‎20% تقريبًا من DisposableEffect. يُرجى العِلم أنّ SideEffect ينفّذ تأثيره قبل DisposableEffect وLaunchedEffect، لذا يجب توخّي الحذر عند نقل التأثيرات الحالية إلى واجهة برمجة التطبيقات هذه، خاصةً بالنسبة إلى 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

النص والإدخال وعمليات التكامل مع المنصات

تنسيق النص القابل للتعديل

توفّر واجهات برمجة التطبيقات الجديدة تنسيق نصوص منسّقة للنصوص القابلة للتعديل في BasicTextField. يمكنك الآن تطبيق تنسيق الأحرف والفقرات المضمّن وتعديله آليًا باستخدام SpanStyle وParagraphStyle من خلال طريقة addStyle() الجديدة داخل نطاق TextFieldBuffer (مثل داخل textFieldState.edit { ... } أو InputTransformation). بالإضافة إلى ذلك، توفّر TextFieldBuffer واجهات برمجة التطبيقات 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 إمكانية التحكّم آليًا في عملية اختيار النص وإمكانية تتبّع البيانات ضمن 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

تتكامل حقول النص في Compose الآن مع واجهة برمجة التطبيقات Credential Manager API في نظام التشغيل Android (المستوى 34 من واجهة برمجة التطبيقات أو الإصدارات الأحدث) من خلال إطار الملء التلقائي (يتم التعامل مع المستوى الأقل من 34 من واجهة برمجة التطبيقات من خلال androidx.credentials library). من خلال ربط السمة الدلالية الجديدة 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 جديدة قابلة للإنشاء للسماح بإيقاف هذه الميزة. يُرجى العِلم أنّه نتيجةً لهذا التغيير، يجب الآن استدعاء أدوات معالجة نقرات الدلالات من سلسلة التعليمات الرئيسية، ما قد يؤثّر في عدد صغير من حالات الاختبار.
  • يتضمّن KeyboardType الآن Date وTime وDateTime و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

تحسينات على أدوات الاختبار

مزامنة الاختبار

تقدّم Compose 1.12 واجهات برمجة تطبيقات جديدة للاختبار مصمَّمة لتقليل أوقات تنفيذ الاختبارات وإزالة عدم الاستقرار أثناء أخذ عيّنات من الحالة:

  • ‫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)
            }
        }
    }
}

التغييرات البارزة الأخرى:

  • تتيح لك واجهة برمجة التطبيقات captureToImage الآن التقاط نافذة منبثقة أو مربّع حوار مع العنصر الأساسي في صورة نقطية واحدة.
  • تمت إضافة onRootWithViewInteraction لتحديد نطاق عمليات البحث الدلالية في Compose لتشمل عروض Android معيّنة. يسهّل ذلك اختبار واجهات المستخدم المختلطة، مثل RecyclerViews، بدون الحاجة إلى علامات اختبار فريدة في رمز الإنتاج.
  • يمكن الآن تطبيق تعليقات @PreviewWrapper التوضيحية على فئات @MultiPreview مخصّصة، ما يتيح إعدادات معاينة قابلة لإعادة الاستخدام (مثل النُسق المخصّصة) على مستوى عناصر متعدّدة.

نتمنى لك التوفيق في تأليف الأغاني.

يسهّل الإصدار 1.12 من Compose عملية تطوير التطبيقات ويجعلها أكثر تعبيرًا من أي وقت مضى، وذلك من خلال توفير تدرّجات شبكية، وإتاحة استخدام مجموعة كبيرة من الألوان، وتوفير خطوط متغيرة قابلة للتنزيل، ودمج "إدارة بيانات الاعتماد"، وتوفير أدوات اختبار أسرع. نقدّر دائمًا ملاحظاتك، لذا يُرجى مشاركتها معنا بشأن هذه التغييرات أو الميزات التي تريد أن نطلقها في المستقبل على أداة تتبُّع المشاكل. نتمنى لك تجربة ممتعة في تأليف الأغاني.

من تأليف:
متابعة القراءة