اخبار محصول

ویژگی‌های جدید در نسخه آوریل ۲۰۲۶ از Jetpack Compose

‫۶ دقیقه خواندن
مشاهده نمایه Meghan Mehta
Meghan Mehta مدافع توسعه‌دهندگان، Android

امروز، نسخه آوریل ۲۰۲۶ Jetpack Compose پایدار است. این نسخه حاوی نسخه ۱.۱۱ از ماژول‌های Compose اصلی (به نگاشت BOM کامل مراجعه کنید)، ابزارهای اشکال‌زدایی عنصر هم‌رسانی‌شده، رویدادهای پد لمسی، و موارد دیگر است. همچنین چند میانای برنامه‌سازی کاربردی آزمایشی داریم که دوست داریم آن‌ها را امتحان کنید و بازخوردتان را به ما ارائه دهید.

برای استفاده از نسخه امروز، نسخه Compose BOM خود را به این نسخه ارتقا دهید:

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

تغییرات در Compose نسخه ۱.۱۱.۰

اجرای Coroutine در آزمایش‌ها

به‌روزرسانی مهمی را در نحوه مدیریت زمان‌بندی آزمایش توسط Compose معرفی می‌کنیم. به‌دنبال دوره موافقت اعلام‌شده در Compose 1.10، میاناهای برنامه‌سازی کاربردی آزمایشی v2 اکنون پیش‌فرض هستند و میاناهای برنامه‌سازی کاربردی v1 منسوخ شده‌اند. تغییر کلیدی، جابه‌جایی در توزیع‌کننده آزمایشی پیش‌فرض است. درحالی‌که میاناهای برنامه‌سازی کاربردی نسخه ۱ به UnconfinedTestDispatcher متکی بودند که کوروتین‌ها را فوراً اجرا می‌کرد، میاناهای برنامه‌سازی کاربردی نسخه ۲ از 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 دارند، کلیک کردن و کشیدن با پد لمسی دیگر پیمایش نخواهد کرد.

همچنین پشتیبانی از اشاره‌های پیچیده‌تر پد لمسی را که از API 34 توسط پلاتفرم شناسایی می‌شود اضافه کردیم، ازجمله تند کشیدن با دو انگشت و نیشگون. این اشاره‌ها به‌طور خودکار توسط مؤلفه‌هایی مثل Modifier.scrollable و Modifier.transformable تشخیص داده می‌شوند تا رفتار بهتری با پدهای لمسی داشته باشند.

این تغییرات رفتار پدهای لمسی را در مؤلفه‌های داخلی بهبود می‌بخشد، با حذف لغزش لمسی زائد، اشاره شروع کشیدن و رها کردن شهودی‌تر، انتخاب با دو کلیک و سه کلیک در فیلدهای نوشتاری، و منوهای زمینه‌ای سبک رایانه در فیلدهای نوشتاری.

برای آزمایش رفتار پد لمسی، میاناهای برنامه‌سازی کاربردی آزمایشی جدیدی با performTrackpadInput, وجود دارد که امکان اعتبارسنجی رفتار برنامه‌هایتان را هنگام استفاده با پد لمسی فراهم می‌کند. اگر تشخیص‌دهنده اشاره سفارشی دارید، رفتار را در انواع ورودی‌ها، ازجمله صفحه‌های لمسی، موشواره‌ها، پدهای لمسی، و قلم‌ها، اعتبارسنجی کنید و از پشتیبانی از چرخ‌های پیمایش موشواره و اشاره‌های پد لمسی اطمینان حاصل کنید.

beforeAndAfter.webp

پیش‌فرض‌های میزبان ترکیب‌بندی (زمان اجرای Compose)

ما HostDefaultProvider، LocalHostDefaultProvider، HostDefaultKey، و ViewTreeHostDefaultKey را معرفی کردیم تا سرویس‌های سطح میزبان را مستقیماً ازطریق compose-runtime ارائه دهیم. این کار نیاز کتابخانه‌ها به وابستگی به compose-ui برای جستجو را برطرف می‌کند و پشتیبانی بهتری از Kotlin Multiplatform ارائه می‌دهد. برای پیوند دادن این مقادیر به درخت ترکیب‌بندی، نویسندگان کتابخانه می‌توانند از compositionLocalWithHostDefaultOf برای ایجاد CompositionLocal استفاده کنند که پیش‌فرض‌ها را از میزبان حل می‌کند.

پیش‌نمایش بسته‌بندی‌ها

پیش‌نمایش‌های سفارشی Android Studio ویژگی جدیدی است که به شما امکان می‌دهد دقیقاً نحوه نمایش محتوای پیش‌نمایش 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 ارتقا خواهد یافت و AGP 9 و همه برنامه‌ها و کتابخانه‌هایی که به Compose وابسته هستند این الزام را به ارث خواهند برد. توصیه می‌کنیم با جدیدترین نسخه‌های منتشرشده به‌روز بمانید، زیرا Compose قصد دارد به‌سرعت compileSdks جدید را اتخاذ کند تا دسترسی به جدیدترین ویژگی‌های Android را فراهم کند. برای کسب اطلاعات بیشتر درباره اینکه کدام نسخه AGP برای سطوح مختلف API پشتیبانی می‌شود، حتماً اسناد را در اینجا بررسی کنید. 

در Compose نسخه ۱.۱۱.۰، میاناهای برنامه‌سازی کاربردی زیر به‌عنوان @Experimental معرفی شده‌اند و مشتاقانه منتظر شنیدن بازخورد شما هنگام کاوش آن‌ها در برنامه‌هایتان هستیم. توجه داشته باشید که @Experimental APIs برای ارزیابی و بازخورد اولیه ارائه شده است و ممکن است در نسخه‌های آتی دستخوش تغییرات قابل‌توجهی شود یا برداشته شود.

سبک‌ها (آزمایشی)

درحال معرفی میانای برنامه‌سازی کاربردی پایه آزمایشی جدیدی برای سبک‌بندی هستیم. Style API الگوی جدیدی برای سفارشی‌سازی عناصر دیداری مؤلفه‌ها است که به‌طور سنتی با اصلاح‌کننده‌ها انجام می‌شده است. این عنصر برای باز کردن قفل سفارشی‌سازی عمیق‌تر و آسان‌تر با نمایش مجموعه‌ای استاندارد از ویژگی‌های قابل‌سبک‌بندی با سبک‌بندی ساده مبتنی بر حالت و انتقال‌های پویانمایی‌شده طراحی شده است. با این میانای برنامه‌سازی کاربردی جدید، درحال‌حاضر شاهد مزایای عملکردی نویدبخشی هستیم. قصد داریم پس‌از تثبیت Style API، از «سبک‌ها» در مؤلفه‌های Material استفاده کنیم.

نمونه‌ای ساده از لغو پس‌زمینه سبک حالت فشرده:

@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 API جدید روشی اعلانی و کارآمد برای تطبیق دادن واسط کاربر با محیط آن ارائه می‌دهد. این تابع بازیابی اطلاعات پیچیده را به شرایط ساده‌ای در یک 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 که هنوز درحال آماده‌سازی هستند) ارزش قائل هستیم — لطفاً آن‌ها را اینجا ثبت کنید. از نوشتن لذت ببرید!

نویسنده:
ادامه خواندن