Kullanıcı arayüzünüzün pencere iç içe eklemeleriyle çalıştığından emin olma

Etkinliğiniz tüm içe yerleştirilen öğelerin işlenmesini kontrol altına aldıktan sonra, içeriğin gizlenmediğinden ve etkileşimli öğelerin sistem kullanıcı arayüzüyle örtüşmediğinden emin olmak için Compose API'lerini kullanabilirsiniz. Bu API'ler, uygulamanızın düzenini de içe yerleştirilen değişikliklerle senkronize eder.

Örneğin, uygulamanızın tamamının içeriğine içe yerleştirilmiş öğeleri uygulamanın en temel yöntemi şudur:

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

    enableEdgeToEdge()

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

Bu snippet, safeDrawing pencere içe eklemelerini uygulamanın tüm içeriğinin etrafına dolgu olarak uygular. Bu, etkileşime açık öğelerin sistem kullanıcı arayüzüyle örtüşmemesini sağlarken uygulamanın hiçbirinin kenardan kenara efekt elde etmek için sistem kullanıcı arayüzünün arkasında çizilmeyeceği anlamına da gelir. Pencerenin tamamını kullanmak için ekranlara veya bileşenlere göre içe yerleştirilen öğelerin uygulandığı yerlerde ince ayar yapmanız gerekir.

Bu içe yerleştirilen türlerin tümü, API 21'e geri bağlanan IME animasyonlarıyla otomatik olarak animasyonlu hale getirilir. Ayrıca, bu iç içe yerleştirilen öğeleri kullanan tüm düzenleriniz, iç içe yerleştirilen öğe değerleri değiştikçe otomatik olarak animasyonlu hale gelir.

Composable düzenlerinizi ayarlamak için bu içe yerleştirilmiş türleri kullanmanın iki temel yolu vardır: dolgu değiştiriciler ve içe yerleştirilmiş boyut değiştiriciler.

Dolgu değiştiriciler

Modifier.windowInsetsPadding(windowInsets: WindowInsets), belirtilen pencere içe eklemelerini tıpkı Modifier.padding gibi dolgu olarak uygular. Örneğin, Modifier.windowInsetsPadding(WindowInsets.safeDrawing) güvenli çizim iç içe eklemelerini 4 tarafın tamamına dolgu olarak uygular.

Ayrıca, en yaygın içe yerleştirilmiş türleri için çeşitli yerleşik yardımcı program yöntemleri de vardır. Modifier.safeDrawingPadding(), Modifier.windowInsetsPadding(WindowInsets.safeDrawing) ile eşdeğer olan bu yöntemlerden biridir. Diğer içe yerleştirilmiş türlerde de benzer değiştiriciler vardır.

İçerik ekleme boyutu değiştiricileri

Aşağıdaki değiştiriciler, bileşenin boyutunu iç içe yerleştirilen öğelerin boyutuna ayarlayarak bir miktar pencere iç içe yerleştirilen öğesi uygular:

Modifier.windowInsetsStartWidth(windowInsets: WindowInsets)

windowInsets öğesinin başlangıç tarafını genişlik olarak uygular (Modifier.width gibi)

Modifier.windowInsetsEndWidth(windowInsets: WindowInsets)

windowInsets öğesinin son tarafını genişlik olarak uygular (Modifier.width gibi)

Modifier.windowInsetsTopHeight(windowInsets: WindowInsets)

windowInsets öğesinin üst tarafını yükseklik olarak uygular (Modifier.height gibi)

Modifier.windowInsetsBottomHeight(windowInsets: WindowInsets)

windowInsets öğesinin alt tarafını yükseklik olarak uygular (Modifier.height gibi)

Bu değiştiriciler, özellikle de iç içe yerleştirilmiş öğelerin alanını kaplayan bir Spacer öğesinin boyutunu belirlemek için yararlıdır:

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

İçe doğru tüketim

İçe yerleştirilen dolgu değiştiricileri (windowInsetsPadding ve safeDrawingPadding gibi yardımcılar), içe yerleştirilenlerin dolgu olarak uygulanan kısmını otomatik olarak tüketir. İç içe yerleştirilmiş iç dolgu değiştiricileri ve iç dolgu boyutu değiştiricileri, kompozisyon ağacında daha derine inerken iç dolguların bir kısmının dış iç dolgu değiştiriciler tarafından zaten kullanıldığını bilir ve iç dolguların aynı kısmını birden fazla kez kullanmaktan kaçınır. Bu da çok fazla ek alan kullanılmasına neden olur.

İçeriği ekleme boyutu değiştiriciler, eklentiler zaten kullanılmışsa aynı eklenti bölümünün birden fazla kez kullanılmasına da engel olur. Ancak boyutlarını doğrudan değiştirdikleri için kendileri yerleşik reklam tüketmez.

Sonuç olarak, iç içe yerleştirilmiş dolgu değiştiriciler her bir kompozit öğeye uygulanan dolgu miktarını otomatik olarak değiştirir.

Önceki LazyColumn örneğine baktığımızda, LazyColumn, imePadding değiştiricisi tarafından yeniden boyutlandırılıyor. LazyColumn içinde, son öğe sistem çubuklarının alt kısmının yüksekliğine göre boyutlandırılır:

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

IME kapalıyken imePadding() değiştirici, IME'nin yüksekliği olmadığı için dolgu uygulamaz. imePadding() değiştiricisi hiçbir dolgu uygulamadığından, içe yerleştirilen öğe kullanılmaz ve Spacer öğesinin yüksekliği, sistem çubuklarının alt tarafının boyutu olur.

IME açıldığında IME içe yerleştirilenleri, IME'nin boyutuna uyacak şekilde animasyonlu olarak ayarlanır ve imePadding() değiştirici, IME açıldığında LazyColumn öğesini yeniden boyutlandırmak için alt dolgu uygulamaya başlar. imePadding() değiştirici alt dolgu uygulamaya başladığında, bu miktarda içe yerleştirilmiş öğe de tüketilmeye başlar. Bu nedenle, sistem çubuklarının aralığı imePadding() değiştiricisi tarafından zaten uygulandığından Spacer öğesinin yüksekliği azalmaya başlar. imePadding() değiştirici, sistem çubuklarından daha büyük bir alt dolgu miktarı uyguladığında Spacer öğesinin yüksekliği sıfır olur.

IME kapandığında değişiklikler ters yönde gerçekleşir: imePadding(), sistem çubuklarının alt tarafından daha az uygulandığında Spacer sıfır yükseklikten genişlemeye başlar. IME tamamen animasyonla kapatıldığında Spacer, sistem çubuklarının alt tarafının yüksekliğiyle eşleşir.

Şekil 2. TextField ile kenardan kenara üşengeç sütun.

Bu davranış, tüm windowInsetsPadding değiştiriciler arasında iletişim kurularak gerçekleştirilir ve birkaç başka şekilde de etkilenebilir.

Modifier.consumeWindowInsets(insets: WindowInsets), Modifier.windowInsetsPadding ile aynı şekilde içe yerleştirilen öğeleri tüketir ancak tüketilen içe yerleştirilen öğeleri dolgu olarak uygulamaz. Bu, belirli miktarda iç içe yerleştirilmiş öğenin zaten kullanıldığını kardeş öğelere belirtmek için iç içe yerleştirilmiş öğe boyutu değiştiricileriyle birlikte kullanışlıdır:

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 bağımsız değişkeni olan sürüme çok benzer şekilde çalışır ancak rastgele bir PaddingValues alır. Bu, dolgu veya aralığın, iç dolgu değiştiricilerden başka bir mekanizma (ör. normal Modifier.padding veya sabit yükseklikli aralıklar) tarafından sağlandığında çocukları bilgilendirmek için kullanışlıdır:

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

Ham pencere içe eklemelerinin tüketim olmadan gerekli olduğu durumlarda doğrudan WindowInsets değerlerini kullanın veya tüketimden etkilenmeyen içe eklemelerin PaddingValues değerini döndürmek için WindowInsets.asPaddingValues() değerini kullanın. Ancak aşağıdaki uyarılar nedeniyle, mümkün olduğunda pencere içe ekleme dolgu değiştiricilerini ve pencere içe ekleme boyutu değiştiricilerini kullanmayı tercih edin.

İçerikler ve Jetpack Compose aşamaları

Compose, iç içe yerleştirilen öğeleri güncellemek ve animasyonlu hale getirmek için temel AndroidX çekirdek API'lerini kullanır. Bu API'ler, iç içe yerleştirilen öğeleri yöneten temel platform API'lerini kullanır. Bu platform davranışı nedeniyle, iç içe yerleştirilmiş içeriklerin Jetpack Compose aşamalarıyla özel bir ilişkisi vardır.

İçe yerleştirilen öğelerin değeri, kompozisyon aşamasından sonra ancak düzen aşamasından önce güncellenir. Bu, kompozisyondaki içe yerleştirilen öğelerin değerinin okunması için genellikle bir kare gecikmeli bir içe yerleştirilen öğe değeri kullanılacağı anlamına gelir. Bu sayfada açıklanan yerleşik değiştiriciler, iç içe yerleştirilmiş öğelerin değerlerinin yerleşim aşamasına kadar kullanılmasının geciktirilmesi için tasarlanmıştır. Bu sayede, iç içe yerleştirilmiş öğe değerleri güncellendikleri karede kullanılır.