اخبار محصول

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

    نوشته شده توسط:
    ادامه مطلب
    ،
    اخبار محصول

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

      نوشته شده توسط:
      ادامه مطلب
      ،
      اخبار محصول

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

        نوشته شده توسط:
        ادامه مطلب
        ،
        اخبار محصول

        ویژگی‌های جدید 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

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

        We're introducing a major update to how Compose handles test timing. Following the opt-in period announced in Compose 1.10, the v2 testing APIs are now the default, and the v1 APIs have been deprecated. The key change is a shift in the default test dispatcher. While the v1 APIs relied on the UnconfinedTestDispatcher , which executed coroutines immediately, the v2 APIs use the StandardTestDispatcher . This means that when a coroutine is launched in your tests, it is now queued and does not execute until the virtual clock is advanced.

        This better mimics production conditions, effectively flushing out race conditions and making your test suite significantly more robust and less flaky.

        To ensure your tests align with standard coroutine behavior and to avoid future compatibility issues, we strongly recommend migrating your test suite. Check out our comprehensive migration guide for API mappings and common fixes.

        Shared element improvements and animation tooling

        We've also added some handy visual debugging tools for shared elements and Modifier.animatedBounds . You can now see exactly what's happening under the hood—like target bounds, animation trajectories, and how many matches are found—making it much easier to spot why a transition might not be behaving as expected. To use the new tooling, simply surround your SharedTransitionLayout with the LookaheadAnimationVisualDebugging composable.

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

        Trackpad events

        We've revamped Compose support for trackpads, like built-in laptop trackpads, attachable trackpads for tablets, or external/virtual trackpads. Basic trackpad events will now generally be considered PointerType.Mouse events, aligning mouse and trackpad behavior to better match user expectations. Previously, these trackpad events were interpreted as fake touchscreen fingers of PointerType.Touch , which led to confusing user experiences. For example, clicking and dragging with a trackpad would scroll instead of selecting. By changing the pointer type these events have in the latest release of Compose, clicking and dragging with a trackpad will no longer scroll.

        We also added support for more complicated trackpad gestures as recognized by the platform since API 34, including two finger swipes and pinches . These gestures are automatically recognized by components like Modifier.scrollable and Modifier.transformable to have better behavior with trackpads.

        These changes improve behavior for trackpads across built-in components, with redundant touch slop removed, a more intuitive drag-and-drop starting gesture, double-click and triple-click selection in text fields, and desktop-styled context menus in text fields.

        To test trackpad behavior, there are new testing APIs with performTrackpadInput , which allow validating the behavior of your apps when being used with a trackpad. If you have custom gesture detectors, validate behavior across input types, including touchscreens, mice, trackpads, and styluses, and ensure support for mouse scroll wheels and trackpad gestures.

        beforeAndAfter.webp

        Composition host defaults (Compose runtime)

        We introduced HostDefaultProvider , LocalHostDefaultProvider , HostDefaultKey , and ViewTreeHostDefaultKey to supply host-level services directly through compose-runtime. This removes the need for libraries to depend on compose-ui for lookups, better supporting Kotlin Multiplatform. To link these values to the composition tree, library authors can use compositionLocalWithHostDefaultOf to create a CompositionLocal that resolves defaults from the host.

        Preview wrappers

        Android Studio custom previews is a new feature that allows you to define exactly how the contents of a Compose preview are displayed.

        By implementing the PreviewWrapperProvider interface and applying the new @PreviewWrapper annotation, you can easily inject custom logic, such as applying a specific Theme . The annotation can be applied to a function annotated with @Composable and @Preview or @MultiPreview , offering a generic, easy-to-use solution that works across preview features and significantly reduces repetitive code.

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

        Deprecations and removals

        • As announced in the Compose 1.10 blog post , we're deprecating Modifier.onFirstVisible() . Its name often led to misconceptions, particularly within lazy layouts, where it would trigger multiple times during scrolling. We recommend migrating to Modifier.onVisibilityChanged() , which allows for more precise manual tracking of visibility states tailored to your specific use case requirements.
        • The ComposeFoundationFlags.isTextFieldDpadNavigationEnabled flag was removed because D-pad navigation for TextFields is now always enabled by default. The new behavior ensures that the D-pad events from a gamepad or a TV remote first move the cursor in the given direction. The focus can move to another element only when the cursor reaches the end of the text.

        Upcoming APIs

        In the upcoming Compose 1.12.0 release, the compileSdk will be upgraded to compileSdk 37 , with AGP 9 and all apps and libraries that depend on Compose inheriting this requirement. We recommend keeping up to date with the latest released versions, as Compose aims to promptly adopt new compileSdks to provide access to the latest Android features. Be sure to check out the documentation here for more information on which version of AGP is supported for different API levels.

        In Compose 1.11.0, the following APIs are introduced as @Experimental , and we look forward to hearing your feedback as you explore them in your apps. Note that @Experimental APIs are provided for early evaluation and feedback and may undergo significant changes or removal in future releases.

        Styles (Experimental)

        We are introducing a new experimental foundation API for styling . The Style API is a new paradigm for customizing visual elements of components, which has traditionally been performed with modifiers. It is designed to unlock deeper, easier customization by exposing a standard set of styleable properties with simple state-based styling and animated transitions. With this new API, we're already seeing promising performance benefits . We plan to adopt Styles in Material components once the Style API stabilizes.

        A basic example of overriding a pressed state style background:

        @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

        Check out the documentation and file any bugs here .

        MediaQuery (Experimental)

        The new mediaQuery API provides a declarative and performant way to adapt your UI to its environment. It abstracts complex information retrieval into simple conditions within a UiMediaScope , ensuring recomposition only happens when needed.

        With support for a wide range of environmental signals—from device capabilities like keyboard types and pointer precision, to contextual states like window size and posture—you can build deeply responsive experiences. Performance is baked in with derivedMediaQuery to handle high-frequency updates, while the ability to override scopes makes testing and previews seamless across hardware configurations. Previously, to get access to certain device properties — like if a device was in tabletop mode — you'd need to write a lot of boilerplate to do so:

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

        Now, with UIMediaQuery , you can add the mediaQuery syntax to query device properties, such as if a device is in tabletop mode:

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

        Check out the documentation and file any bugs here .

        Grid (Experimental)

        Grid is a powerful new API for building complex, two-dimensional layouts in Jetpack Compose. While Row and Column are great for linear designs, Grid gives you the structural control needed for screen-level architecture and intricate components without the overhead of a scrollable list. Grid allows you to define your layout using tracks, gaps, and cells, offering familiar sizing options like Dp , percentages, intrinsic content sizes, and flexible "Fr" units.

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

        You can place items automatically or explicitly span them across multiple rows and columns for precision. Best of all, it's highly adaptive—you can dynamically reconfigure your grid tracks and spans to respond to device states like tabletop mode or orientation changes, ensuring your UI looks great across form factors.

        Grid.gif

        Check out the documentation and file any bugs here .

        FlexBox (Experimental)

        FlexBox is a layout container designed for high performance, adaptive UIs. It manages item sizing and space distribution based on available container dimensions. It handles complex tasks like wrapping ( wrap ) and multi-axis alignment of items ( justifyContent, alignItems, alignContent ). It allows items to grow ( grow ) or shrink ( shrink ) to fill the container.

        @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

        Check out the documentation and file any bugs here .

        New SlotTable implementation (Experimental)

        We've introduced a new implementation of the SlotTable , which is disabled by default in this release. SlotTable is the internal data structure that the Compose runtime uses to track the state of your composition hierarchy, track invalidations/recompositions, store remembered values, and track all metadata of the composition at runtime. This new implementation is designed to improve performance, primarily around random edits.

        To try the new SlotTable , enable ComposeRuntimeFlags.isLinkBufferComposerEnabled .

        Start coding today!

        With so many exciting new APIs in Jetpack Compose, and many more coming up, it's never been a better time to migrate to Jetpack Compose . As always, we value your feedback and feature requests (especially on @Experimental features that are still baking) — please file them here . Happy composing!

          نوشته شده توسط:
          ادامه مطلب