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

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

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

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

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

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

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

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

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

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

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

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

أضفنا أيضًا بعض أدوات تصحيح الأخطاء المرئية المفيدة للعناصر المشتركة و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 أصبح مفعَّلاً دائمًا بشكل تلقائي. يضمن السلوك الجديد أن تؤدي أحداث لوحة التحكّم من جهاز تحكّم في الألعاب أو جهاز تحكّم عن بُعد للتلفزيون إلى تحريك المؤشر أولاً في الاتجاه المحدّد. ويمكن نقل التركيز إلى عنصر آخر فقط عندما يصل المؤشر إلى نهاية النص.

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

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

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

الأنماط (ميزة تجريبية)

نقدّم واجهة برمجة تطبيقات أساسية تجريبية جديدة للتنسيق. تُعدّ واجهة Style API نموذجًا جديدًا لتخصيص العناصر المرئية للمكوّنات، والتي كان يتم تنفيذها عادةً باستخدام المُعدِّلات. وهي مصمَّمة لإتاحة تخصيص أعمق وأسهل من خلال عرض مجموعة معايير التعلُّم من السمات القابلة للتنسيق مع تنسيق بسيط مستند إلى الحالة وانتقالات متحركة. من خلال واجهة برمجة التطبيقات الجديدة هذه، نلاحظ بالفعل مزايا واعدة في الأداء. نخطّط لاعتماد الأنماط في مكوّنات Material Design بعد أن تصبح واجهة 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 التي لا تزال قيد التطوير)، لذا يُرجى إرسالها هنا. نتمنى لك تجربة ممتعة.

من كتابة:
متابعة القراءة