راه اندازی ورودی های پنجره

زمانی که Activity شما کنترل مدیریت تمام insetها را به دست گرفت، می‌توانید از Compose APIها برای تأیید اینکه محتوا مبهم نیست و عناصر قابل تعامل با رابط کاربری سیستم همپوشانی ندارند، استفاده کنید. این APIها همچنین طرح‌بندی برنامه شما را با تغییرات inset همگام‌سازی می‌کنند.

با استفاده از padding یا اصلاح‌کننده‌های اندازه، insetها را مدیریت کنید

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

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

    enableEdgeToEdge()

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

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

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

سه روش برای مدیریت درج‌ها (insets) جهت تنظیم طرح‌بندی‌های Composable شما وجود دارد:

اصلاح‌کننده‌های فاصله‌گذاری

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

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

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

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

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ها را مصرف نمی‌کنند.

در نتیجه، اصلاح‌کننده‌های تودرتوی padding به طور خودکار میزان padding اعمال شده به هر composable را تغییر می‌دهند.

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

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

وقتی IME بسته است، اصلاح‌کننده imePadding() هیچ فاصله‌ای اعمال نمی‌کند، زیرا IME ارتفاعی ندارد. از آنجایی که اصلاح‌کننده imePadding() هیچ فاصله‌ای اعمال نمی‌کند، هیچ inset ای مصرف نمی‌شود و ارتفاع Spacer به اندازه ضلع پایین میله‌های سیستم خواهد بود.

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

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

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

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

Modifier.consumeWindowInsets(insets: WindowInsets) نیز مانند Modifier.windowInsetsPadding از insetها استفاده می‌کند، اما insetهای مصرف‌شده را به عنوان padding اعمال نمی‌کند. این در ترکیب با اصلاح‌کننده‌های اندازه 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 ​​دلخواه برای مصرف می‌گیرد. این برای اطلاع‌رسانی به عناصر فرعی در زمانی که فاصله‌گذاری یا فاصله‌گذاری توسط مکانیسم دیگری غیر از اصلاح‌کننده‌های padding درج، مانند یک Modifier.padding معمولی یا فاصله‌گذارهای با ارتفاع ثابت، ارائه می‌شود، مفید است:

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

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

مراحل درج و نوشتن با جت‌پک

Compose از APIهای اصلی AndroidX برای به‌روزرسانی و متحرک‌سازی insetها استفاده می‌کند که از APIهای پلتفرم اصلی برای مدیریت insetها استفاده می‌کنند. به دلیل همین رفتار پلتفرم، insetها رابطه ویژه‌ای با مراحل Jetpack Compose دارند.

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