راه‌اندازی حاشیه‌های پنجره

وقتی «فعالیت» شما کنترل مدیریت همه درج‌ها را به‌دست گرفت، می‌توانید از Compose APIs استفاده کنید تا مطمئن شوید محتوا پنهان نمی‌شود و عناصر تعاملی با رابط کاربری سیستم هم‌پوشانی ندارند. این میاناهای برنامه‌سازی کاربردی همچنین چیدمان برنامه‌تان را با تغییرات درج همگام‌سازی می‌کنند.

مدیریت کردن حاشیه‌های داخلی بااستفاده از اصلاح‌کننده‌های اندازه یا فاصله‌گذاری

برای مثال، این ابتدایی‌ترین روش اعمال درج‌ها به محتوای کل برنامه شما است:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    enableEdgeToEdge()

    setContent {
        Box(Modifier.safeDrawingPadding()) {
            // the rest of the app
        }
    }
}

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

همه این انواع درج به‌طور خودکار با پویانمایی‌های IME که به API 21 منتقل شده‌اند، پویانمایی می‌شوند. به‌علاوه، همه چیدمان‌های شما که از این تورفتگی‌ها استفاده می‌کنند با تغییر مقادیر تورفتگی به‌طور خودکار پویانمایی می‌شوند.

سه روش برای مدیریت تورفتگی‌ها جهت تنظیم طرح‌بندی‌های Composable وجود دارد:

اصلاح‌کننده‌های لایه

Modifier.windowInsetsPadding(windowInsets: WindowInsets) درج‌های پنجره داده‌شده را به‌عنوان حاشیه داخلی اعمال می‌کند و دقیقاً مانند Modifier.padding عمل می‌کند. برای مثال، Modifier.windowInsetsPadding(WindowInsets.safeDrawing) درج‌های طراحی ایمن را به‌عنوان حاشیه داخلی در هر ۴ طرف اعمال می‌کند.

همچنین چندین روش کاربردی داخلی برای رایج‌ترین انواع درج وجود دارد. Modifier.safeDrawingPadding() یکی از این روش‌ها است که معادل Modifier.windowInsetsPadding(WindowInsets.safeDrawing) است. جدول زیر اصلاح‌کننده‌های لایه داخلی توکار و نوع WindowInsets را که هرکدام اعمال می‌کنند فهرست می‌کند:

Modifier.safeDrawingPadding()

WindowInsets.safeDrawing

Modifier.safeGesturesPadding()

WindowInsets.safeGestures

Modifier.safeContentPadding()

WindowInsets.safeContent

Modifier.statusBarsPadding()

WindowInsets.statusBars

Modifier.navigationBarsPadding()

WindowInsets.navigationBars

Modifier.captionBarPadding()

WindowInsets.captionBar

Modifier.systemBarsPadding()

WindowInsets.systemBars

Modifier.imePadding()

WindowInsets.ime

Modifier.systemGesturesPadding()

WindowInsets.systemGestures

Modifier.mandatorySystemGesturesPadding()

WindowInsets.mandatorySystemGestures

Modifier.displayCutoutPadding()

WindowInsets.displayCutout

Modifier.waterfallPadding()

WindowInsets.waterfall

برای اینکه ببینید هر نوع درج چه چیزی را پوشش می‌دهد، به درباره درج‌های پنجره مراجعه کنید.

اصلاح‌کننده‌های اندازه درج

اصلاح‌کننده‌های زیر با تنظیم اندازه مؤلفه به‌اندازه تورفتگی‌ها، مقداری تورفتگی پنجره اعمال می‌کنند:

Modifier.windowInsetsStartWidth(windowInsets: WindowInsets)

سمت شروع windowInsets را به‌عنوان عرض اعمال می‌کند (مانند Modifier.width)

Modifier.windowInsetsEndWidth(windowInsets: WindowInsets)

سمت پایانی windowInsets را به‌عنوان عرض اعمال می‌کند (مانند Modifier.width)

Modifier.windowInsetsTopHeight(windowInsets: WindowInsets)

سمت بالای windowInsets را به‌عنوان ارتفاع اعمال می‌کند (مثل Modifier.height)

Modifier.windowInsetsBottomHeight(windowInsets: WindowInsets)

سمت پایین windowInsets را به‌عنوان ارتفاع اعمال می‌کند (مانند Modifier.height)

این اصلاح‌کننده‌ها به‌ویژه برای اندازه‌گیری Spacer که فضای درج‌ها را اشغال می‌کند مفید هستند:

LazyColumn(
    Modifier.imePadding()
) {
    // Other content
    item {
        Spacer(
            Modifier.windowInsetsBottomHeight(
                WindowInsets.systemBars
            )
        )
    }
}

مصرف درج‌شده

اصلاح‌کننده‌های لایه داخلی (windowInsetsPadding و کمک‌کننده‌هایی مانند safeDrawingPadding) به‌طور خودکار بخشی از لایه‌های داخلی را که به‌عنوان لایه داخلی اعمال می‌شوند، مصرف می‌کنند. هنگام عمیق‌تر شدن در درخت ترکیب، اصلاح‌کننده‌های تودرتو پدینگ inset و اصلاح‌کننده‌های اندازه inset می‌دانند که بخشی از insetها قبلاً توسط اصلاح‌کننده‌های پدینگ inset بیرونی مصرف شده‌اند و از استفاده مجدد از همان بخش insetها خودداری می‌کنند که منجر به فضای اضافی بیش از حد می‌شود.

اصلاح‌کننده‌های اندازه درج نیز از استفاده بیش‌از یک‌بار از همان بخش درج‌ها جلوگیری می‌کنند اگر درج‌ها قبلاً مصرف شده باشند. بااین‌حال، چون اندازه خود را مستقیماً تغییر می‌دهند، خودشان حاشیه‌ها را مصرف نمی‌کنند.

As a result, nesting padding modifiers automatically change the amount of padding applied to each composable.

با نگاه کردن به همان مثال LazyColumn قبلی، اندازه LazyColumn توسط اصلاح‌گر imePadding تغییر می‌کند. درون LazyColumn، اندازه آخرین مورد به‌اندازه ارتفاع پایین نوارهای سیستم است:

LazyColumn(
    Modifier.imePadding()
) {
    // Other content
    item {
        Spacer(
            Modifier.windowInsetsBottomHeight(
                WindowInsets.systemBars
            )
        )
    }
}

وقتی IME بسته است، imePadding() هیچ فاصله‌گذاری‌ای اعمال نمی‌کند. درنتیجه، هیچ حاشیه‌ای مصرف نمی‌شود و ارتفاع Spacer با نوارهای سیستم پایین مطابقت دارد.

وقتی IME باز می‌شود، حاشیه‌های IME متحرک می‌شوند تا با اندازه IME مطابقت داشته باشند، و imePadding() اصلاح‌کننده شروع به اعمال لایه پایین می‌کند تا اندازه LazyColumn را با باز شدن IME تغییر دهد. وقتی اصلاح‌کننده imePadding() شروع به اعمال حاشیه داخلی پایین می‌کند، شروع به مصرف آن مقدار از حاشیه‌های داخلی نیز می‌کند. بنابراین، ارتفاع Spacer شروع به کاهش می‌کند، زیرا بخشی از فاصله‌گذاری برای نوارهای سیستم قبلاً توسط اصلاح‌کننده imePadding() اعمال شده است. وقتی اصلاح‌کننده imePadding() مقدار حاشیه داخلی پایینی را که بزرگ‌تر از نوار سیستم است اعمال می‌کند، ارتفاع Spacer صفر است.

وقتی IME بسته می‌شود، تغییرات به‌صورت معکوس اتفاق می‌افتد: Spacer از ارتفاع صفر گسترش می‌یابد زیرا imePadding() کمتر از نوارهای سیستم پایین اعمال می‌شود. درنهایت، وقتی IME کاملاً از حالت پویانمایی خارج می‌شود، ارتفاع Spacer با نوارهای سیستم مطابقت پیدا می‌کند.

شکل ۲. ستون تنبل لبه‌به‌لبه با TextField.

این رفتار ازطریق ارتباط بین همه اصلاح‌کننده‌های windowInsetsPadding انجام می‌شود و می‌تواند به چند روش دیگر تحت‌تأثیر قرار گیرد.

Modifier.consumeWindowInsets(insets: WindowInsets) نیز به‌همان روش Modifier.windowInsetsPadding از حاشیه‌های داخلی استفاده می‌کند، اما حاشیه‌های داخلی استفاده‌شده را به‌عنوان لایه اعمال نمی‌کند. این ویژگی در ترکیب با اصلاح‌کننده‌های اندازه inset مفید است تا به عناصر هم‌سطح نشان دهد که مقدار مشخصی از inset قبلاً مصرف شده است:

Column(Modifier.verticalScroll(rememberScrollState())) {
    Spacer(Modifier.windowInsetsTopHeight(WindowInsets.systemBars))

    Column(
        Modifier.consumeWindowInsets(
            WindowInsets.systemBars.only(WindowInsetsSides.Vertical)
        )
    ) {
        // content
        Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime))
    }

    Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.systemBars))
}

Modifier.consumeWindowInsets(paddingValues: PaddingValues) رفتاری بسیار مشابه با نسخه دارای آرگومان WindowInsets دارد، اما یک PaddingValues دلخواه را برای مصرف می‌گیرد. این برای اطلاع دادن به فرزندان مفید است، وقتی‌که فاصله‌گذاری یا حاشیه داخلی توسط سازوکار دیگری غیراز اصلاح‌کننده‌های حاشیه داخلی درج‌شده ارائه می‌شود، مانند Modifier.padding معمولی یا فاصله‌گذارهای با ارتفاع ثابت:

Column(Modifier.padding(16.dp).consumeWindowInsets(PaddingValues(16.dp))) {
    // content
    Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime))
}

در مواردی که به درج‌های پنجره خام بدون مصرف نیاز است، مستقیماً از مقادیر WindowInsets استفاده کنید، یا از WindowInsets.asPaddingValues() برای برگرداندن PaddingValues درج‌هایی که تحت‌تأثیر مصرف قرار نگرفته‌اند استفاده کنید. بااین‌حال، به‌دلیل هشدارهای زیر، ترجیحاً هرجا ممکن بود از اصلاح‌کننده‌های لایی درج‌های پنجره و اصلاح‌کننده‌های اندازه درج‌های پنجره استفاده کنید.

مراحل Insets و Jetpack Compose

Compose از میاناهای برنامه‌سازی کاربردی هسته AndroidX برای به‌روزرسانی و پویانمایی درج‌ها استفاده می‌کند، که از میاناهای برنامه‌سازی کاربردی پلاتفرم زیربنایی مدیریت درج‌ها استفاده می‌کنند. به‌دلیل آن رفتار پلاتفرم، تورفتگی‌ها رابطه ویژه‌ای با فازهای Jetpack Compose دارند.

مقدار تورفتگی‌ها بعداز فاز ترکیب‌بندی، اما قبل‌از فاز چیدمان به‌روز می‌شود. این یعنی خواندن مقدار تورفتگی‌ها در ترکیب‌بندی عموماً از مقدار تورفتگی‌هایی استفاده می‌کند که یک فریم تأخیر دارد. اصلاح‌کننده‌های داخلی شرح‌داده‌شده در این صفحه به‌گونه‌ای ساخته شده‌اند که استفاده از مقادیر درج‌ها را تا مرحله چیدمان به‌تأخیر بیندازند، که این امر تضمین می‌کند مقادیر درج در همان فریمی که به‌روزرسانی می‌شوند استفاده شوند.