اخبار محصول

ویژگی‌های جدید Jetpack Compose نسخه آوریل 26

مطالعه ۵ دقیقه‌ای
Meghan Mehta
وکیل توسعه‌دهندگان، اندروید

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

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

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

تغییرات در Compose 1.11.0

اجرای کوروتین در تست‌ها

ما در حال معرفی یک به‌روزرسانی عمده در نحوه مدیریت زمان‌بندی تست توسط Compose هستیم. پس از دوره انتخاب اعلام شده در Compose 1.10، APIهای تست نسخه ۲ اکنون پیش‌فرض هستند و APIهای نسخه ۱ منسوخ شده‌اند. تغییر کلیدی، تغییر در توزیع‌کننده تست پیش‌فرض است. در حالی که APIهای نسخه ۱ به UnconfinedTestDispatcher متکی بودند که کوروتین‌ها را بلافاصله اجرا می‌کرد، APIهای نسخه ۲ از StandardTestDispatcher استفاده می‌کنند. این بدان معناست که وقتی یک کوروتین در تست‌های شما راه‌اندازی می‌شود، اکنون در صف قرار می‌گیرد و تا زمانی که ساعت مجازی به جلو نرود، اجرا نمی‌شود.

این امر شرایط تولید را بهتر شبیه‌سازی می‌کند، به طور مؤثر شرایط رقابتی را از بین می‌برد و مجموعه تست شما را به طور قابل توجهی قوی‌تر و کمتر شکننده می‌کند.

برای اطمینان از اینکه تست‌های شما با رفتار استاندارد کوروتین همسو هستند و برای جلوگیری از مشکلات سازگاری در آینده، اکیداً توصیه می‌کنیم مجموعه تست خود را مهاجرت دهید. برای نگاشت‌های API و اصلاحات رایج ، راهنمای جامع مهاجرت ما را بررسی کنید.

بهبودهای عناصر مشترک و ابزارهای انیمیشن

ما همچنین چند ابزار اشکال‌زدایی بصری مفید برای عناصر مشترک و 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 شناسایی می‌شوند تا رفتار بهتری با ترک‌پدها داشته باشند.

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

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

beforeAndAfter.webp

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

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

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

پیش‌نمایش‌های سفارشی اندروید استودیو یک ویژگی جدید است که به شما امکان می‌دهد دقیقاً نحوه نمایش محتوای پیش‌نمایش Compose را تعریف کنید.

با پیاده‌سازی رابط PreviewWrapperProvider و اعمال حاشیه‌نویسی جدید @PreviewWrapper ، می‌توانید به راحتی منطق سفارشی، مانند اعمال یک Theme خاص، را تزریق کنید. این حاشیه‌نویسی را می‌توان به تابعی که با @Composable و @Preview یا @MultiPreview حاشیه‌نویسی شده است، اعمال کرد و یک راه‌حل عمومی و آسان برای استفاده ارائه داد که در تمام ویژگی‌های پیش‌نمایش کار می‌کند و کد تکراری را به میزان قابل توجهی کاهش می‌دهد.

class ThemeWrapper: PreviewWrapper {
    @Composable
    override fun Wrap(content: @Composable (() -> Unit)) {
        JetsnackTheme {
            content()
        }
    }
}

@PreviewWrapperProvider(ThemeWrapper::class)
@Preview
@Composable
private fun ButtonPreview() {
    // JetsnackTheme in effect
    Button(onClick = {}) {
        Text(text = "Demo")
    }
}

منسوخ‌ها و حذف‌ها

  • همانطور که در پست وبلاگ Compose 1.10 اعلام شد، ما Modifier.onFirstVisible() منسوخ می‌کنیم. نام آن اغلب منجر به تصورات غلط، به ویژه در طرح‌بندی‌های تنبل، می‌شد، جایی که در طول پیمایش چندین بار فعال می‌شد. ما توصیه می‌کنیم به Modifier.onVisibilityChanged() مهاجرت کنید، که امکان ردیابی دستی دقیق‌تر حالت‌های دید متناسب با الزامات مورد استفاده خاص شما را فراهم می‌کند.
  • پرچم ComposeFoundationFlags.isTextFieldDpadNavigationEnabled حذف شد زیرا پیمایش با D-pad برای TextFields اکنون همیشه به طور پیش‌فرض فعال است. این رفتار جدید تضمین می‌کند که رویدادهای D-pad از یک دسته بازی یا کنترل تلویزیون ابتدا مکان‌نما را در جهت داده شده حرکت می‌دهند. فوکوس فقط زمانی می‌تواند به عنصر دیگری منتقل شود که مکان‌نما به انتهای متن برسد.

API های آینده

در نسخه آتی Compose 1.12.0، compileSdk به compileSdk 37 ارتقا خواهد یافت و AGP 9 و تمام برنامه‌ها و کتابخانه‌هایی که به Compose وابسته هستند، این الزام را به ارث می‌برند. توصیه می‌کنیم از آخرین نسخه‌های منتشر شده به‌روز باشید، زیرا Compose قصد دارد به سرعت compileSdks جدید را برای دسترسی به جدیدترین ویژگی‌های اندروید اتخاذ کند. برای اطلاعات بیشتر در مورد اینکه کدام نسخه از AGP برای سطوح مختلف API پشتیبانی می‌شود، حتماً مستندات اینجا را بررسی کنید.

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

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

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

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

@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",
        )
    }
}
سبک‌ها.webp

مستندات را بررسی کنید و هرگونه اشکالی را اینجا ثبت کنید.

مدیاکوئری (آزمایشی)

رابط برنامه‌نویسی کاربردی جدید 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 یک API جدید و قدرتمند برای ساخت طرح‌بندی‌های پیچیده و دوبعدی در 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()
    }
}

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

شبکه.gif

مستندات را بررسی کنید و هرگونه اشکالی را اینجا ثبت کنید.

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

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) })
    }
}
انیمیشنGif.gif

مستندات را بررسی کنید و هرگونه اشکالی را اینجا ثبت کنید.

پیاده‌سازی جدید SlotTable (آزمایشی)

ما پیاده‌سازی جدیدی از SlotTable را معرفی کرده‌ایم که به طور پیش‌فرض در این نسخه غیرفعال است. SlotTable ساختار داده داخلی است که زمان اجرای Compose برای ردیابی وضعیت سلسله مراتب ترکیب شما، ردیابی نامعتبرسازی‌ها/بازترکیب‌ها، ذخیره مقادیر به خاطر سپرده شده و ردیابی تمام فراداده‌های ترکیب در زمان اجرا از آن استفاده می‌کند. این پیاده‌سازی جدید برای بهبود عملکرد، در درجه اول در مورد ویرایش‌های تصادفی، طراحی شده است.

برای امتحان کردن SlotTable جدید، ComposeRuntimeFlags.isLinkBufferComposerEnabled را فعال کنید.

همین امروز کدنویسی را شروع کنید!

با وجود این همه API جدید و هیجان‌انگیز در Jetpack Compose و بسیاری دیگر که در راه هستند، هیچ زمانی بهتر از الان برای مهاجرت به Jetpack Compose نبوده است. مثل همیشه، ما برای بازخوردها و درخواست‌های شما برای ویژگی‌های جدید (به‌خصوص در مورد ویژگی‌های @Experimental که هنوز در حال توسعه هستند) ارزش قائلیم - لطفاً آنها را اینجا ثبت کنید. از نوشتن لذت ببرید!

    نوشته شده توسط:

    ادامه مطلب