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

الميزات الجديدة في إصدار أبريل 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"))

التغييرات في الإصدار 1.11.0 من Compose

تنفيذ الروتينات المشتركة في الاختبارات

نحن بصدد طرح تحديث رئيسي على طريقة تعامل 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-runtime. يؤدي ذلك إلى إزالة الحاجة إلى أن تعتمد المكتبات على 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")
    }
}

الميزات التي سيتم إيقافها نهائيًا وإزالتها

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

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

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

في الإصدار 1.11.0 من Compose، تم طرح واجهات برمجة التطبيقات التالية كواجهات @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 هي واجهة برمجة تطبيقات جديدة وفعّالة لإنشاء تصاميم معقّدة ثنائية الأبعاد في 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 الميزات (خاصةً تلك التي لا تزال قيد التطوير) — يُرجى إرسالها هنا. نتمنى لك تجربة ممتعة في تأليف الأغاني.

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