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

ما الجديد في إصدار أبريل 2026 من Jetpack Compose؟

مدّة القراءة: 6 دقائق
عرض الملف الشخصي لـ Meghan Mehta
Meghan Mehta مسؤولة علاقات المطوّرين، Android

أصبح إصدار أبريل 2026 من Jetpack Compose مستقرًا اليوم. يتضمّن هذا الإصدار الإصدار 1.11 من وحدات Compose الأساسية (راجِع ربط قائمة إدارة مواد العرض الكاملة) وأدوات تصحيح أخطاء العناصر المشترَكة وأحداث لوحة التتبّع والمزيد. لدينا أيضًا بعض واجهات برمجة التطبيقات التجريبية التي نودّ أن تجربها وتزوّدنا بملاحظاتك عنها.

لاستخدام إصدار اليوم، عليك ترقية إصدار قائمة إدارة مواد العرض في Compose إلى:

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

التغييرات في Compose 1.11.0

تنفيذ الروتينات الفرعية في الاختبارات

نقدّم تعديلاً رئيسيًا على طريقة تعامل Compose مع توقيت الاختبار. بعد فترة الاشتراك الاختياري التي تم الإعلان عنها في Compose 1.10، أصبحت الآن واجهات برمجة التطبيقات للاختبار في الإصدار 2 هي الإعدادات التلقائية، وتم إيقاف واجهات برمجة التطبيقات في الإصدار 1 نهائيًا. التغيير الرئيسي هو تحويل موجّه الاختبار التلقائي. في حين أنّ واجهات برمجة التطبيقات في الإصدار 1 كانت تعتمد على UnconfinedTestDispatcher الذي كان ينفّذ الروتينات الفرعية على الفور، تستخدم واجهات برمجة التطبيقات في الإصدار 2 StandardTestDispatcher. هذا يعني أنّه عند تشغيل روتين فرعي في اختباراتك، يتم الآن وضعه في قائمة الانتظار ولا يتم تنفيذه إلى أن يتم تقديم الساعة الافتراضية.

يحاكي ذلك بشكل أفضل ظروف الإنتاج، ما يؤدي إلى إزالة حالات التنافس بشكل فعّال ويجعل مجموعة الاختبارات أكثر قوة وأقل عرضة للخطأ بشكل ملحوظ.

لضمان توافق اختباراتك مع السلوك العادي للروتينات الفرعية وتجنُّب مشاكل التوافق المستقبلية، ننصحك بشدة بنقل مجموعة الاختبارات. راجِع دليل نقل البيانات الشامل للاطّلاع على عمليات ربط واجهات برمجة التطبيقات والإصلاحات الشائعة.

تحسينات على العناصر المشترَكة وأدوات الصور المتحركة

أضفنا أيضًا بعض أدوات تصحيح الأخطاء المرئية المفيدة للعناصر المشترَكة وModifier.animatedBounds. يمكنك الآن الاطّلاع على ما يحدث بالضبط في الخلفية، مثل الحدود المستهدَفة ومسارات الصور المتحركة وعدد النتائج المطابقة التي تم العثور عليها، ما يسهّل كثيرًا تحديد سبب عدم تصرّف الانتقال على النحو المتوقّع. لاستخدام الأدوات الجديدة، ما عليك سوى إحاطة SharedTransitionLayout بالدالة الإنشائية LookaheadAnimationVisualDebugging

LookaheadAnimationVisualDebugging(
    overlayColor = Color(0x4AE91E63),
    isEnabled = true,
    multipleMatchesColor = Color.Green,
    isShowKeylabelEnabled = false,
    unmatchedElementColor = Color.Red,
) {
    SharedTransitionLayout {
        CompositionLocalProvider(
            LocalSharedTransitionScope provides this,
        ) {
            // your content
        }
    }
}

أحداث لوحة التتبّع

لقد جدّدنا إمكانية استخدام لوحات التتبّع في Compose، مثل لوحات التتبّع المضمّنة في أجهزة الكمبيوتر المحمولة أو لوحات التتبّع القابلة للتوصيل بالأجهزة اللوحية أو لوحات التتبّع الخارجية أو الافتراضية. سيتم الآن بشكل عام اعتبار أحداث لوحة التتبّع الأساسية أحداث PointerType.Mouse، ما يوفّر سلوكًا متوافقًا بين الماوس ولوحة التتبّع ليتطابق بشكل أفضل مع توقّعات المستخدمين. في السابق، كانت تُفسَّر أحداث لوحة التتبّع هذه على أنّها أصابع شاشة لمس وهمية من PointerType.Touch، ما كان يؤدي إلى تجارب مستخدمين مربِكة. على سبيل المثال، كان النقر والسحب باستخدام لوحة التتبّع يؤديان إلى التمرير بدلاً من الاختيار. من خلال تغيير نوع المؤشر لهذه الأحداث في أحدث إصدار من Compose، لن يؤدي النقر والسحب باستخدام لوحة التتبّع إلى التمرير بعد الآن.

أضفنا أيضًا إمكانية استخدام إيماءات لوحة التتبّع الأكثر تعقيدًا التي تتعرّف عليها المنصة منذ الإصدار 34 من واجهة برمجة التطبيقات، بما في ذلك التمرير السريع بإصبعَين و التقريب والتصغير. تتعرّف المكوّنات تلقائيًا على هذه الإيماءات، مثل Modifier.scrollable وModifier.transformable، للحصول على سلوك أفضل مع لوحات التتبّع.

تؤدي هذه التغييرات إلى تحسين سلوك لوحات التتبّع في المكوّنات المضمّنة، مع إزالة مسافة السحب غير الضرورية، وإيماءة السحب والإفلات الأولية الأكثر سهولة، والاختيار بالنقر المزدوج والنقر الثلاثي في حقول النصوص، وقوائم السياق بنمط الكمبيوتر المكتبي في حقول النصوص.

لاختبار سلوك لوحة التتبّع، تتوفّر واجهات برمجة تطبيقات جديدة للاختبار تتضمّن performTrackpadInput, ما يتيح التحقق من سلوك تطبيقاتك عند استخدامها مع لوحة تتبّع. إذا كانت لديك أدوات رصد إيماءات مخصّصة، تحقَّق من السلوك في جميع أنواع الإدخال، بما في ذلك شاشات اللمس والماوس ولوحات التتبّع والأقلام، وتأكَّد من إمكانية استخدام عجلات تمرير الماوس وإيماءات لوحة التتبّع.

beforeAndAfter.webp

الإعدادات التلقائية لمضيف التركيب (وقت تشغيل Compose)

لقد طرحنا HostDefaultProvider وLocalHostDefaultProvider وHostDefaultKey وViewTreeHostDefaultKey لتقديم الخدمات على مستوى المضيف مباشرةً من خلال وقت تشغيل Compose. يزيل ذلك حاجة المكتبات إلى الاعتماد على compose-ui لعمليات البحث، ما يحسّن دعم Kotlin Multiplatform. لربط هذه القيم بشجرة التركيب، يمكن لمؤلّفي المكتبات استخدام compositionLocalWithHostDefaultOf لإنشاء CompositionLocal يحلّ الإعدادات التلقائية من المضيف.

أغلفة المعاينة

المعاينات المخصّصة في "استوديو Android" هي ميزة جديدة تتيح لك تحديد طريقة عرض محتوى معاينة Compose بالضبط.

من خلال تنفيذ واجهة PreviewWrapperProvider وتطبيق التعليق التوضيحي الجديد @PreviewWrapper، يمكنك بسهولة إدخال منطق مخصّص، مثل تطبيق Theme معيّن. يمكن تطبيق التعليق التوضيحي على دالة تم وضع التعليق التوضيحي @Composable و@Preview أو @MultiPreview عليها، ما يوفّر حلاً عامًا وسهل الاستخدام يعمل على مستوى ميزات المعاينة ويقلّل بشكل كبير من التعليمات البرمجية المتكرّرة.

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

الإيقاف النهائي والإزالة

  • كما تم الإعلان في مشاركة المدونة Compose 1.10، سنوقف نهائيًا استخدام Modifier.onFirstVisible(). غالبًا ما كان اسمها يؤدي إلى مفاهيم خاطئة، خاصةً في التنسيقات المؤجّلة، حيث كان يتم تشغيلها عدة مرات أثناء التمرير. ننصحك بنقل البيانات إلى Modifier.onVisibilityChanged()، ما يتيح تتبُّع حالات الرؤية يدويًا بشكل أكثر دقة بما يتناسب مع متطلبات حالة الاستخدام المحدّدة.
  • تمت إزالة العلامة ComposeFoundationFlags.isTextFieldDpadNavigationEnabled لأنّه يتم الآن دائمًا تفعيل التنقّل باستخدام لوحة المفاتيح الرباعية الاتجاهات في TextFields تلقائيًا. يضمن السلوك الجديد أنّ أحداث لوحة المفاتيح الرباعية الاتجاهات من لوحة ألعاب أو جهاز تحكّم عن بُعد في التلفزيون تحرّك المؤشر أولاً في الاتجاه المحدّد. لا يمكن نقل التركيز إلى عنصر آخر إلا عندما يصل المؤشر إلى نهاية النص.

واجهات برمجة التطبيقات القادمة

في الإصدار القادم من Compose 1.12.0، ستتم ترقية compileSdk إلى compileSdk 37، مع الإصدار 9 من المكوّن الإضافي لنظام Gradle المتوافق مع Android وجميع التطبيقات والمكتبات التي تعتمد على Compose والتي ستكتسب هذا المتطلب. ننصحك بالاطّلاع على أحدث الإصدارات التي تم طرحها، لأنّ Compose يهدف إلى اعتماد compileSdks الجديدة على الفور لتوفير إمكانية الوصول إلى أحدث ميزات Android. احرص على الاطّلاع على المستندات هنا لمزيد من المعلومات حول إصدار المكوّن الإضافي لنظام Gradle المتوافق مع Android المتوافق مع مستويات واجهة برمجة التطبيقات المختلفة. 

في Compose 1.11.0، يتم طرح واجهات برمجة التطبيقات التالية على أنّها @Experimental، ونتطلّع إلى تلقّي ملاحظاتك أثناء استكشافها في تطبيقاتك. يُرجى العِلم أنّ @Experimental APIs يتم توفيرها للتقييم المبكر وتلقّي الملاحظات، وقد تخضع لتغييرات كبيرة أو تتم إزالتها في الإصدارات المستقبلية.

التصاميم (تجريبية)

نقدّم واجهة برمجة تطبيقات أساسية تجريبية جديدة للتصميم. ‫Style API هي نموذج جديد لتخصيص العناصر المرئية للمكوّنات، والتي كانت تُجرى تقليديًا باستخدام المعدِّلات. تم تصميمها لتوفير تخصيص أعمق وأسهل من خلال عرض مجموعة عادية من الخصائص القابلة للتصميم مع تصميم بسيط يستند إلى الحالة وعمليات انتقال متحركة. باستخدام واجهة برمجة التطبيقات الجديدة هذه، نحقّق بالفعل تحسينات واعدة في الأداء. نخطط لاعتماد التصاميم في مكوّنات Material بعد أن تصبح Style API مستقرة.

في ما يلي مثال أساسي على إلغاء خلفية تصميم حالة الضغط:

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

راجِع المستندات وأبلِغ عن أي أخطاء هنا.

‫MediaQuery (تجريبية)

توفر واجهة برمجة التطبيقات الجديدة mediaQuery طريقة تعريفية وعالية الأداء لتكييف واجهة المستخدم مع بيئتها. تجرّد هذه الواجهة عملية استرجاع المعلومات المعقّدة إلى شروط بسيطة ضمن UiMediaScope، ما يضمن إعادة التركيب فقط عند الحاجة.

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

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

الآن، باستخدام UIMediaQuery، يمكنك إضافة بنية mediaQuery للاستعلام عن خصائص الجهاز، مثل ما إذا كان الجهاز في وضع سطح المنضدة:

@OptIn(ExperimentalMediaQueryApi::class)
@Composable
fun VideoPlayer() {
    if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) {
        TabletopLayout()
    } else {
        FlatLayout()
    }
}

راجِع المستندات وأبلِغ عن أي أخطاء هنا.

‫Grid (تجريبية)

Grid هي واجهة برمجة تطبيقات جديدة فعّالة لإنشاء تنسيقات معقّدة ثنائية الأبعاد في Jetpack Compose. في حين أنّ Row وColumn رائعتان للتصاميم الخطية، تمنحك Grid التحكّم الهيكلي اللازم لبنية على مستوى الشاشة والمكوّنات المعقّدة بدون تكلفة إضافية لقائمة قابلة للتمرير. تتيح لك Grid تحديد التنسيق باستخدام المسارات والفواصل والخلايا، ما يوفّر خيارات تغيير الحجم المألوفة، مثل Dp والنسب المئوية وأحجام المحتوى الأساسية ووحدات "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()
    }
}

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

Grid.gif

راجِع المستندات وأبلِغ عن أي أخطاء هنا

‫FlexBox (تجريبية)

FlexBox هو حاوية تنسيق مصمّمة لواجهات مستخدم عالية الأداء وقابلة للتكيّف. تُدير هذه الحاوية تغيير حجم العناصر وتوزيع المساحة استنادًا إلى أبعاد الحاوية المتاحة.وتتعامل مع المهام المعقّدة، مثل الالتفاف (wrap) ومحاذاة العناصر على مستوى محاور متعددة (justifyContent, alignItems, alignContent). وتسمح للعناصر بالتوسّع (grow) أو الانكماش (shrink) لملء الحاوية. 

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

راجِع المستندات وأبلِغ عن أي أخطاء هنا.

تنفيذ جديد لـ SlotTable (تجريبي)

لقد طرحنا تنفيذًا جديدًا لـ SlotTable، وهو غير مفعّل تلقائيًا في هذا الإصدار. SlotTable هي بنية البيانات الداخلية التي يستخدمها وقت تشغيل Compose لتتبُّع حالة التسلسل الهرمي للتركيب، وتتبُّع عمليات الإبطال/إعادة التركيب، وتخزين القيم التي تم تذكّرها، وتتبُّع جميع بيانات وصف التركيب في وقت التشغيل. تم تصميم هذا التنفيذ الجديد لتحسين الأداء، خاصةً في ما يتعلق بالتعديلات العشوائية.

لتجربة SlotTable الجديدة، فعِّل ComposeRuntimeFlags.isLinkBufferComposerEnabled

ابدأ الترميز اليوم.

مع توفّر العديد من واجهات برمجة التطبيقات الجديدة والمثيرة في Jetpack Compose، والعديد من واجهات برمجة التطبيقات القادمة، لم يكن هناك وقت أفضل من الآن للنقل إلى Jetpack Compose.  كالعادة، نقدّر ملاحظاتك وطلبات الميزات (خاصةً بشأن الميزات @Experimental التي لا تزال قيد التطوير)، لذا يُرجى إرسالها هنا. نتمنّى لك تجربة ممتعة في إنشاء المحتوى.

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