Listeler ve ızgaralar

Birçok uygulamanın, öğe koleksiyonlarını görüntülemesi gerekir. Bu dokümanda, bunu Jetpack Compose'da nasıl verimli bir şekilde yapabileceğiniz açıklanmaktadır.

Kullanım alanınızın herhangi bir kaydırma gerektirmediğini biliyorsanız, basit bir Column veya Row kullanın (yöne bağlı olarak) ve her bir öğenin içeriğini yineleme şu şekilde yapılır:

@Composable
fun MessageList(messages: List<Message>) {
    Column {
        messages.forEach { message ->
            MessageRow(message)
        }
    }
}

verticalScroll() değiştiricisini kullanarak Column'i kaydırılabilir hale getirebiliriz.

Tembel listeler

Çok sayıda öğe (veya uzunluğu bilinmeyen bir liste) görüntülemeniz gerekiyorsa Column gibi bir düzen kullanmak, tüm öğeler oluşturulacağı ve görünür olup olmadıklarına göre düzenleneceği için performans sorunlarına neden olabilir.

Oluşturma, yalnızca aşağıdaki durumlarda olan öğeleri oluşturan ve düzenleyen bileşenlerin görüntü alanında görünür olması gerekir. Bu bileşenler şunları içerir: LazyColumn ve LazyRow.

Adından da anlaşılacağı gibi, LazyColumn ile LazyRow arasındaki fark, öğelerin düzenlenme ve kaydırma yönüdür. LazyColumn dikey kaydırmalı bir liste, LazyRow ise yatay kaydırmalı bir liste oluşturur.

Yavaş bileşenler, Oluştur'daki çoğu düzenden farklıdır. Uygulamaların doğrudan bileşen yayınlamasına izin veren bir @Composable içerik bloğu parametresi kabul etmek yerine, yavaş bileşenler bir LazyListScope.() bloğu sağlar. Bu LazyListScope bloğu, uygulamaların öğe içeriklerini açıklamasına olanak tanıyan bir DSL sunar. İlgili içeriği oluşturmak için kullanılan Daha sonra Tembel bileşen, her bir öğenin içeriğini göre değişir.

LazyListScope DSL

LazyListScope DSL'si, öğeleri açıklamak için çeşitli işlevler sağlar tıklayın. En basit haliyle, item() tek bir öğe, items(Int) ise birden fazla öğe ekler:

LazyColumn {
    // Add a single item
    item {
        Text(text = "First item")
    }

    // Add 5 items
    items(5) { index ->
        Text(text = "Item: $index")
    }

    // Add another single item
    item {
        Text(text = "Last item")
    }
}

Çok sayıda uzantıya metin eklememize olanak tanıyan öğe koleksiyonları, List gibi. Bu uzantılar, reklamımızı yukarıdaki Column örneğimizi taşıyın:

/**
 * import androidx.compose.foundation.lazy.items
 */
LazyColumn {
    items(messages) { message ->
        MessageRow(message)
    }
}

Ayrıca, items() uzantı işlevi itemsIndexed(), Böylece dizini sağlar. Daha fazla bilgi için lütfen LazyListScope inceleyebilirsiniz.

Yavaş ızgaralar

LazyVerticalGrid ve LazyHorizontalGrid bileşenleri, öğeleri ızgarada görüntüleme desteği sağlar. Tembel dikey ızgara öğelerini dikey olarak kaydırılabilen bir kapsayıcıda görüntüler. Tembel yatay ızgaralar ise aynı davranışa sahip olacak, ancak Tembel yatay ızgaralar yatay eksende yer alır.

Izgaralar, listelerle aynı güçlü API özelliklerine sahiptir ve aynı zamanda bir çok benzer DSL LazyGridScope.() tercih edebilirsiniz.

Izgara düzeninde fotoğrafların gösterildiği bir telefonun ekran görüntüsü

LazyVerticalGrid içindeki columns parametresi ve LazyHorizontalGrid içindeki rows parametresi, hücrelerin sütun veya satır halinde nasıl oluşturulacağını kontrol eder. Aşağıdaki örnekte, her sütunu en az 128.dp genişliğinde ayarlamak için GridCells.Adaptive kullanılarak öğeler ızgara şeklinde gösterilmektedir:

LazyVerticalGrid(
    columns = GridCells.Adaptive(minSize = 128.dp)
) {
    items(photos) { photo ->
        PhotoItem(photo)
    }
}

LazyVerticalGrid, öğeler için bir genişlik belirtmenizi sağlar, ardından ızgara sütuna sığdırırsınız. Kalan genişlik eşit olarak dağıtılır sütun sayısı hesaplandıktan sonra bu değerleri görebilirsiniz. Bu uyarlanabilir boyutlandırma yöntemi, özellikle farklı ekran boyutlarında öğe grupları görüntülemek için yararlıdır.

Kullanılacak sütun sayısını tam olarak biliyorsanız bunun yerine, gerekli sütun sayısını içeren bir GridCells.Fixed örneği sağlayabilirsiniz.

Tasarımınız yalnızca belirli öğelerin standart olmayan boyutlara sahip olmasını gerektiriyorsa öğeler için özel sütun aralıkları sağlamak üzere ızgara desteğini kullanabilirsiniz. Sütun kapsamını, LazyGridScope DSL item ve items yöntemlerinin span parametresiyle belirtin. maxLineSpan span kapsamının değerlerinden biri, özellikle uyarlanabilir boyutlandırma, çünkü sütun sayısı sabit değildir. Bu örnekte, tam satır kapsamının nasıl sağlanacağı gösterilmektedir:

LazyVerticalGrid(
    columns = GridCells.Adaptive(minSize = 30.dp)
) {
    item(span = {
        // LazyGridItemSpanScope:
        // maxLineSpan
        GridItemSpan(maxLineSpan)
    }) {
        CategoryCard("Fruits")
    }
    // ...
}

Eğik ızgara

LazyVerticalStaggeredGrid ve LazyHorizontalStaggeredGrid geç yüklenen, kademeli bir öğe ızgarası oluşturmanızı sağlayan composable'lardır. Yavaş dikey kademeli ızgara, öğelerini birden fazla sütuna yayılan ve öğelerin farklı yüksekliklere sahip olmasına olanak tanıyan dikey olarak kaydırılabilir bir kapsayıcıda gösterir. Yavaş yatay ızgaralar, farklı genişlikteki öğelerle yatay eksende aynı davranışı gösterir.

Aşağıdaki snippet, LazyVerticalStaggeredGrid kullanımına ilişkin temel bir örnektir öğe başına 200.dp genişlikle:

LazyVerticalStaggeredGrid(
    columns = StaggeredGridCells.Adaptive(200.dp),
    verticalItemSpacing = 4.dp,
    horizontalArrangement = Arrangement.spacedBy(4.dp),
    content = {
        items(randomSizedPhotos) { photo ->
            AsyncImage(
                model = photo,
                contentScale = ContentScale.Crop,
                contentDescription = null,
                modifier = Modifier.fillMaxWidth().wrapContentHeight()
            )
        }
    },
    modifier = Modifier.fillMaxSize()
)

Şekil 1. Tembel dikey ızgara örneği
'nı inceleyin.

Sabit sayıda sütun ayarlamak için: StaggeredGridCells.Adaptive yerine StaggeredGridCells.Fixed(columns). Bu işlem, mevcut genişliği sütun sayısına (veya yatay ızgara için satır sayısına) böler ve her bir öğenin bu genişliği (veya yatay ızgara için yüksekliği) kaplamasını sağlar:

LazyVerticalStaggeredGrid(
    columns = StaggeredGridCells.Fixed(3),
    verticalItemSpacing = 4.dp,
    horizontalArrangement = Arrangement.spacedBy(4.dp),
    content = {
        items(randomSizedPhotos) { photo ->
            AsyncImage(
                model = photo,
                contentScale = ContentScale.Crop,
                contentDescription = null,
                modifier = Modifier.fillMaxWidth().wrapContentHeight()
            )
        }
    },
    modifier = Modifier.fillMaxSize()
)
Oluştur&#39;daki resimlerin ızgara şeklinde yan yana sarmalanması
Şekil 2. Sabit sütunlara sahip kademeli dikey ızgara örneği
'nı inceleyin.

İçerik doldurma

Bazen içeriğin kenarlarına dolgu eklemeniz gerekir. Yavaş bileşenler, bunu desteklemek için contentPadding parametresine bazı PaddingValues iletmenize olanak tanır:

LazyColumn(
    contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp),
) {
    // ...
}

Bu örnekte, yatay kenarlara (sol ve alt kenarlara) 16.dp oranında dolgu ekliyoruz. sağda), ardından içeriğin üst ve alt kısmına 8.dp tuşlarına basın.

Bu dolgunun LazyColumn kendisi. Yukarıdaki örnekte ilk öğeye 8.dp eklenir üst kısmına dolgu eklerseniz son öğe, en alta 8.dp ve tüm öğeler eklenir sol ve sağ tarafta 16.dp dolgu olacak.

İçerik aralığı

Öğeler arasında boşluk eklemek için şunları kullanabilirsiniz: Arrangement.spacedBy(). Aşağıdaki örnekte, her öğe arasına 4.dp boşluk eklenmiştir:

LazyColumn(
    verticalArrangement = Arrangement.spacedBy(4.dp),
) {
    // ...
}

LazyRow için de benzer şekilde:

LazyRow(
    horizontalArrangement = Arrangement.spacedBy(4.dp),
) {
    // ...
}

Ancak ızgaralar hem dikey hem de yatay düzenlemeleri kabul eder:

LazyVerticalGrid(
    columns = GridCells.Fixed(2),
    verticalArrangement = Arrangement.spacedBy(16.dp),
    horizontalArrangement = Arrangement.spacedBy(16.dp)
) {
    items(photos) { item ->
        PhotoItem(item)
    }
}

Öğe anahtarları

Varsayılan olarak her öğenin durumu, öğenin listedeki veya tablodaki konumuna göre anahtarlanır. Ancak, konumu değişen öğeler hatırlanan durumu etkili bir şekilde kaybettiği için veri kümesi değişirse bu durum sorunlara neden olabilir. Tahmin edebileceğiniz gibi LazyColumn içindeki LazyRow senaryosunda satır, öğe konumunu değiştirirse bunun ardından kullanıcı, satırdaki kaydırma konumunu kaybeder.

.

Bununla mücadele etmek amacıyla, her öğe için sabit ve benzersiz bir anahtar sağlayarak key parametresi için bir blok. Sabit bir anahtar sağlamak, öğe durumunun ve veri kümesi değişiklikleri arasında tutarlılık sağlar:

LazyColumn {
    items(
        items = messages,
        key = { message ->
            // Return a stable + unique key for the item
            message.id
        }
    ) { message ->
        MessageRow(message)
    }
}

Anahtarlar sağlayarak Compose'un yeniden sıralamayı doğru şekilde işlemesine yardımcı olursunuz. Örneğin, öğeniz hatırlanan durum içeriyorsa ayar anahtarları, konumu değiştiğinde Oluştur'un bu durumu öğeyle birlikte taşımasına olanak tanır.

LazyColumn {
    items(books, key = { it.id }) {
        val rememberedValue = remember {
            Random.nextInt()
        }
    }
}

Ancak öğe anahtarı olarak kullanabileceğiniz türlerle ilgili bir sınırlama vardır. Anahtarın türü, etkinlik yeniden oluşturulduğunda durumları korumak için Android'in mekanizması olan Bundle tarafından desteklenmelidir. Bundle, ilkel, enum veya Parcelables gibi türleri destekler.

LazyColumn {
    items(books, key = {
        // primitives, enums, Parcelable, etc.
    }) {
        // ...
    }
}

Anahtar, Bundle tarafından desteklenmelidir. Böylece, etkinlik yeniden oluşturulduğunda veya bu öğeden uzaklaşıp geri geldiğinizde bile, öğe bileşiğinin içindeki rememberSaveable geri yüklenebilir.

LazyColumn {
    items(books, key = { it.id }) {
        val rememberedValue = rememberSaveable {
            Random.nextInt()
        }
    }
}

Öğe animasyonları

RecyclerView widget'ını kullandıysanız öğe değişikliklerini otomatik olarak animasyonlu hale getirdiğini bilirsiniz. Tembel düzenler, öğelerin yeniden sıralanması için aynı işlevi sağlar. API basittir; tek yapmanız gereken animateItemPlacement değiştiricisi:

LazyColumn {
    // It is important to provide a key to each item to ensure animateItem() works as expected.
    items(books, key = { it.id }) {
        Row(Modifier.animateItem()) {
            // ...
        }
    }
}

Şunlara ihtiyacınız varsa özel animasyon spesifikasyonu bile sağlayabilirsiniz:

LazyColumn {
    items(books, key = { it.id }) {
        Row(
            Modifier.animateItem(
                fadeInSpec = tween(durationMillis = 250),
                fadeOutSpec = tween(durationMillis = 100),
                placementSpec = spring(stiffness = Spring.StiffnessLow, dampingRatio = Spring.DampingRatioMediumBouncy)
            )
        ) {
            // ...
        }
    }
}

Taşınan öğenin yeni konumunu bulmak için öğeleriniz için anahtar sağladığınızdan emin olun.

Yeniden sıralamanın yanı sıra, ekleme ve kaldırma işlemleri için öğe animasyonları şu anda geliştirilme aşamasındadır. İlerleme durumunu 150812265 numaralı destek kaydından takip edebilirsiniz.

Yapışkan üstbilgiler (deneysel)

"Yapışkan başlık" kalıbı, gruplandırılmış verilerin listelerini görüntülerken kullanışlıdır. Aşağıda her kişinin iletişim bilgilerine göre gruplandırılmış bir "kişi listesi" örneğini görebilirsiniz ilk:

Bir telefonda kişiler listesinde yukarı ve aşağı kaydırma yapan bir video

LazyColumn ile sabit bir başlık oluşturmak için deneysel stickyHeader() işlevini kullanın:

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ListWithHeader(items: List<Item>) {
    LazyColumn {
        stickyHeader {
            Header()
        }

        items(items) { item ->
            ItemRow(item)
        }
    }
}

Yukarıdaki "kişiler listesi" örneğinde olduğu gibi, birden çok başlık içeren bir listeye ulaşmak için yapabilecekleriniz:

// This ideally would be done in the ViewModel
val grouped = contacts.groupBy { it.firstName[0] }

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ContactsList(grouped: Map<Char, List<Contact>>) {
    LazyColumn {
        grouped.forEach { (initial, contactsForInitial) ->
            stickyHeader {
                CharacterHeader(initial)
            }

            items(contactsForInitial) { contact ->
                ContactListItem(contact)
            }
        }
    }
}

Kaydırma konumuna tepki verme

Birçok uygulamanın kaydırma konumu ve öğe düzeni değişikliklerine tepki vermesi ve bu değişiklikleri dinlemesi gerekir. Tembel bileşenler, tembel bileşenleri kaldırarak bu kullanım alanını LazyListState:

@Composable
fun MessageList(messages: List<Message>) {
    // Remember our own LazyListState
    val listState = rememberLazyListState()

    // Provide it to LazyColumn
    LazyColumn(state = listState) {
        // ...
    }
}

Basit kullanım alanlarında, uygulamaların genellikle yalnızca ilk görünür öğeyle ilgili bilgileri bilmesi gerekir. Bunun için LazyListState sağlar firstVisibleItemIndex ve firstVisibleItemScrollOffset özellikler.

Kullanıcının kaydırarak ilk öğeyi geçip geçmediğine bağlı olarak bir düğmeyi gösterme ve gizleme örneğini kullanırsak:

@Composable
fun MessageList(messages: List<Message>) {
    Box {
        val listState = rememberLazyListState()

        LazyColumn(state = listState) {
            // ...
        }

        // Show the button if the first visible item is past
        // the first item. We use a remembered derived state to
        // minimize unnecessary compositions
        val showButton by remember {
            derivedStateOf {
                listState.firstVisibleItemIndex > 0
            }
        }

        AnimatedVisibility(visible = showButton) {
            ScrollToTopButton()
        }
    }
}

Durumu doğrudan kompozisyonda okumak, güncelleme yapmanız gerektiğinde yararlıdır kullanıcı arayüzü composable'ları oluşturur, ancak etkinliğin aynı bileşimde ele alınacaktır. Bunun yaygın bir örneği, kullanıcı belirli bir noktanın ötesine geçtiğinde bir Analytics etkinliği göndermektir. Bunu yapmak için etkili bir şekilde, snapshotFlow():

val listState = rememberLazyListState()

LazyColumn(state = listState) {
    // ...
}

LaunchedEffect(listState) {
    snapshotFlow { listState.firstVisibleItemIndex }
        .map { index -> index > 0 }
        .distinctUntilChanged()
        .filter { it }
        .collect {
            MyAnalyticsService.sendScrolledPastFirstItemEvent()
        }
}

LazyListState, layoutInfo mülkü aracılığıyla şu anda gösterilen tüm öğeler ve ekrandaki sınırları hakkında da bilgi sağlar. Daha fazla bilgi için LazyListLayoutInfo sınıfına bakın.

Kaydırma konumunu kontrol etme

Ayrıca, kaydırma konumuna tepki vermenin yanı sıra uygulamaların, kaydırma konumunu da kontrol edebilirsiniz. LazyListState scrollToItem() üzerinden bunu destekler işlevini "hemen" kaydırma konumu ve animateScrollToItem() Örneğin, animasyon (yumuşak kaydırma olarak da bilinir) ile kayan resim:

@Composable
fun MessageList(messages: List<Message>) {
    val listState = rememberLazyListState()
    // Remember a CoroutineScope to be able to launch
    val coroutineScope = rememberCoroutineScope()

    LazyColumn(state = listState) {
        // ...
    }

    ScrollToTopButton(
        onClick = {
            coroutineScope.launch {
                // Animate scroll to the first item
                listState.animateScrollToItem(index = 0)
            }
        }
    )
}

Büyük veri kümeleri (sayfalama)

Sayfalama kitaplığı, uygulamaların büyük öğe listelerini desteklemesini sağlar. Bu kitaplık, gerektiğinde listenin küçük parçalarını yükleyip gösterir. Sayfalandırma 3.0 ve sonraki sürümler, androidx.paging:paging-compose kitaplığı aracılığıyla Oluştur desteği sağlar.

Sayfalandırılmış içerik listesini görüntülemek için collectAsLazyPagingItems() fonksiyonunu çağırın ve daha sonra, döndürülen LazyPagingItems LazyColumn içinde items() adlı yere. Görünümlerdeki Sayfalama desteğine benzer şekilde, item değerinin null olup olmadığını kontrol ederek veriler yüklenirken yer tutucular gösterebilirsiniz:

@Composable
fun MessageList(pager: Pager<Int, Message>) {
    val lazyPagingItems = pager.flow.collectAsLazyPagingItems()

    LazyColumn {
        items(
            lazyPagingItems.itemCount,
            key = lazyPagingItems.itemKey { it.id }
        ) { index ->
            val message = lazyPagingItems[index]
            if (message != null) {
                MessageRow(message)
            } else {
                MessagePlaceholder()
            }
        }
    }
}

Yavaş düzenleri kullanmayla ilgili ipuçları

Yavaş oluşturulan düzenlerinizin amaçlandığı gibi çalıştığından emin olmak için dikkate alabileceğiniz birkaç ipucu vardır.

0 piksel boyutunda öğeler kullanmaktan kaçının

Bu durum, örneğin eşzamansız olarak yapmayı beklediğiniz senaryolarda gerçekleşebilir daha sonra listenizin öğelerini doldurmak için resimler gibi bazı verileri alabilir. Bu durumda, öğelerin yüksekliği 0 piksel olduğu ve tüm öğeler görüntü alanına sığabileceği için, tembel düzenin tüm öğelerini ilk ölçümde oluşturmasına neden olur. Öğeler yüklendikten ve yükseklikleri genişletildikten sonra, Tembel düzenler oluşturulan diğer öğeleri de siler ve gereksiz yere çünkü görüntü alanına sığmazlar. Bunu önlemek için öğelerinize varsayılan boyutlandırmayı ayarlamanız gerekir. Böylece, yavaş düzen, görüntü alanına kaç öğenin sığabileceğini doğru şekilde hesaplayabilir:

@Composable
fun Item(imageUrl: String) {
    AsyncImage(
        model = rememberAsyncImagePainter(model = imageUrl),
        modifier = Modifier.size(30.dp),
        contentDescription = null
        // ...
    )
}

Veriler tamamlandıktan sonra, öğelerinizin yaklaşık bedenini eşzamansız olarak yüklendiğinde, öğelerinizin bedenlerinin değişmediğinden aynısını yapın (örneğin, birkaç yer tutucu ekleyerek). Bu, kaydırmanın doğru konumda kalmasına yardımcı olur.

Aynı yönde kaydırılabilir bileşenleri iç içe yerleştirmekten kaçının

Bu durum yalnızca, önceden tanımlanmış bir boyut olmadan kaydırılabilir alt öğelerin aynı yönde kaydırılabilir başka bir üst öğe içine yerleştirildiği durumlarda geçerlidir. Örneğin, sabit yüksekliği olmayan bir alt LazyColumn öğesini dikey olarak kaydırılabilir bir öğenin içine yerleştir Column ebeveyn:

// throws IllegalStateException
Column(
    modifier = Modifier.verticalScroll(state)
) {
    LazyColumn {
        // ...
    }
}

Bunun yerine, tüm composable'larınızı sarmalayarak aynı sonucu elde edebilirsiniz. LazyColumn ve DSL'yi kullanarak farklı türde içerik. Bu, hem tekli öğelerin hem de birden çok liste öğesinin atanmasına olanak tanır. tek bir yerden kontrol edebilirsiniz:

LazyColumn {
    item {
        Header()
    }
    items(data) { item ->
        PhotoItem(item)
    }
    item {
        Footer()
    }
}

Farklı yön düzenlerini iç içe yerleştirdiğiniz durumlarda (ör. kaydırılabilir bir üst öğe Row ve bir alt öğe LazyColumn) izin verildiğini unutmayın:

Row(
    modifier = Modifier.horizontalScroll(scrollState)
) {
    LazyColumn {
        // ...
    }
}

Aynı yön düzenlerini kullanmaya devam ettiğiniz ancak iç içe yerleştirilmiş alt öğelere sabit bir boyuttur:

Column(
    modifier = Modifier.verticalScroll(scrollState)
) {
    LazyColumn(
        modifier = Modifier.height(200.dp)
    ) {
        // ...
    }
}

Tek bir öğeye birden çok öğe yerleştirmemeye dikkat edin

Bu örnekte, ikinci öğe lambda'sı tek bir blokta 2 öğe yayar:

LazyVerticalGrid(
    columns = GridCells.Adaptive(100.dp)
) {
    item { Item(0) }
    item {
        Item(1)
        Item(2)
    }
    item { Item(3) }
    // ...
}

Tembel düzenler bunu beklendiği gibi ele alarak öğeleri bir düzende yerleştirir. farklı öğelermiş gibi davranırlar. Ancak bu yöntemin bazı sorunları vardır.

Birden fazla öğe tek bir öğenin parçası olarak yayınlandığında tek bir varlık olarak ele alınır. Bu nedenle, artık tek tek derlenemezler. Ekranda bir öğe görünür hale gelirse öğeye karşılık gelen tüm öğelerin oluşturulması ve ölçülmesi gerekir. Bu, kullanılırsa performansı düşürebilir aşırıya kaçmamak gerekir. Tüm öğeleri tek bir öğeye koymanın ekstrem bir örneği Bu, Tembel düzenlerin kullanılmasının amacını tamamen ortadan kaldırır. Olası performans sorunlarının yanı sıra, bir öğeye daha fazla öğe eklemek scrollToItem() ve animateScrollToItem() ile de etkileşime girer.

Bununla birlikte, bir öğeye birden fazla öğe eklemenin geçerli kullanım alanları vardır (ör. bir listede ayırıcılar kullanmak). Ayırıcıların kaydırmayı değiştirmesini istemiyorsunuz bağımsız unsurlar olarak değerlendirilmemeleri gerekir. Ayrıca, bölücüler küçük olduğundan performans da etkilenmez. Bölücünün, önceki öğenin parçası olabilmesi için önceki öğe görünür olduğunda görünür olması gerekir:

LazyVerticalGrid(
    columns = GridCells.Adaptive(100.dp)
) {
    item { Item(0) }
    item {
        Item(1)
        Divider()
    }
    item { Item(2) }
    // ...
}

Özel düzenlemeler kullanmayı düşünün

Tembel listelerde genellikle birçok öğe bulunur ve bunlar, tembel listelerden daha büyük bir kaydırma kapsayıcısını kullanın. Ancak listeniz az sayıda öğeyle doldurulduğunda, bu öğelerin görüntü alanında nasıl konumlandırılacağıyla ilgili tasarımınız için daha spesifik gereksinimler olabilir.

Bunun için özel sektör Arrangement LazyColumn'a iletebiliriz. Aşağıdaki örnekte, TopWithFooter nesnenin yalnızca arrange yöntemini uygulaması gerekir. İlk olarak, videoyu öğeleri üst üste koyacaksınız. İkinci olarak, kullanılan toplam yükseklik alt görüntü alanı yüksekliğini belirlerse alt bilgi en alta yerleştirilir:

object TopWithFooter : Arrangement.Vertical {
    override fun Density.arrange(
        totalSize: Int,
        sizes: IntArray,
        outPositions: IntArray
    ) {
        var y = 0
        sizes.forEachIndexed { index, size ->
            outPositions[index] = y
            y += size
        }
        if (y < totalSize) {
            val lastIndex = outPositions.lastIndex
            outPositions[lastIndex] = totalSize - sizes.last()
        }
    }
}

contentType adlı kullanıcıyı eklemeyi düşünün

Lazy'nizin performansını en üst düzeye çıkarmak için Compose 1.2'den başlayın. veya düzene eklemek için contentType listelerinizdeki ya da ızgaralarınızda. Bu, her biri için içerik türünü belirtmenize olanak tanır. bir liste veya ızgara oluşturduğunuz durumlarda, düzenin öğe türünden bahsedeceğiz:

LazyColumn {
    items(elements, contentType = { it.type }) {
        // ...
    }
}

contentType Oluştur, yalnızca besteleri yeniden kullanabilir aynı türden öğeler arasında olmalıdır. Yeniden kullanmak aynı yapıda öğeler oluşturmak, içerik türlerinin sağlanması, Oluşturma işlemi, tamamen aynı olan A türü bir öğe oluşturmaya B türünde farklı bir öğedir. Bu, kompozisyonun faydalarını en üst düzeye çıkarmaya ve Tembel düzen performansınız.

Performansı ölçme

Tembel düzenin performansını yalnızca yayınlama modu ve R8 optimizasyonunun etkin olduğu anlamına gelir. Hata ayıklama derlemelerinde, Geç düzen Kaydırma daha yavaş görünebilir. Daha fazla bilgi için Performans oluşturun.