Wear OS için Compose içeren listeler


Listeler, kullanıcıların Wear OS cihazlarda bir dizi seçenek arasından öğe seçmesine olanak tanır.

Birçok Wear OS cihazda yuvarlak ekran kullanıldığından ekranın üst ve alt kısımlarında görünen liste öğelerini görmek daha zordur. Bu nedenle, Wear OS için Compose'da LazyColumn sınıfının TransformingLazyColumn adlı bir sürümü bulunur. Bu sürüm, ölçeklendirme ve şekil değiştirme animasyonlarını destekler. Kenarlara doğru hareket eden öğeler küçülür ve soluklaşır.

Önerilen ölçeklendirme ve kaydırma efektlerini uygulamak için:

  1. Öğe ekranda kaydırılırken Compose'un yükseklik değişikliğini hesaplamasına izin vermek için Modifier.transformedHeight kullanın.
  2. Öğe içeriklerini küçültme de dahil olmak üzere görsel efektleri uygulamak için transformation = SurfaceTransformation(transformationSpec) kısayolunu kullanın.
  3. transformation parametresini almayan bileşenler (ör. Text) için özel bir TransformationSpec kullanın.

Aşağıdaki animasyonda, bir liste öğesinin ekranın üst ve alt kısımlarına yaklaştığında nasıl ölçeklendiği ve şekil değiştirdiği gösterilmektedir:

Aşağıdaki kod snippet'inde, TransformingLazyColumn düzenini kullanarak çeşitli Wear OS ekran boyutlarında harika görünen içerikler oluşturmak için nasıl liste oluşturulacağı gösterilmektedir.

Snippet'te, listenin üst ve alt kısmında doğru dolguyu uygulamak için liste öğelerinde ayarlamanız gereken minimumVerticalContentPadding değiştiricisinin kullanımı da gösterilmektedir.

Kaydırma göstergesini göstermek için ScreenScaffold ile TransformingLazyColumn arasındaki columnState değerini paylaşın:

val columnState = rememberTransformingLazyColumnState()
val transformationSpec = rememberTransformationSpec()
ScreenScaffold(
    scrollState = columnState
) { contentPadding ->
    TransformingLazyColumn(
        state = columnState,
        contentPadding = contentPadding
    ) {
        item {
            ListHeader(
                modifier = Modifier
                    .fillMaxWidth()
                    .transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(ListHeaderDefaults.minimumTopListContentPadding),
                transformation = SurfaceTransformation(transformationSpec)
            ) {
                Text(text = "Header")
            }
        }
        // ... other items
        item {
            Button(
                modifier = Modifier
                    .fillMaxWidth()
                    .transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(ButtonDefaults.minimumVerticalListContentPadding),
                transformation = SurfaceTransformation(transformationSpec),
                onClick = { /* ... */ },
                icon = {
                    Icon(
                        imageVector = Icons.Default.Build,
                        contentDescription = "build",
                    )
                },
            ) {
                Text(
                    text = "Build",
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                )
            }
        }
    }
}

Snap-and-fling efekti ekleme

Sabitleme, kullanıcının kaydırma veya hızlı kaydırma hareketini tamamladığında listenin, genellikle ekranın ortası olmak üzere belirli bir noktada tam olarak konumlandırılmış bir öğeyle yerleşmesini sağlar. Öğelerin merkezden uzaklaştıkça ölçeklendiği ve dönüştüğü yuvarlak ekranlarda, en alakalı öğenin optimum görüntüleme alanında tamamen görünür ve okunabilir kalmasını sağlamak için tutturma özelliği özellikle yararlıdır.

Bir yapıştır ve fırlat davranışı eklemek için flingBehavior parametresini TransformingLazyColumnDefaults.snapFlingBehavior(columnState) olarak ayarlayın. Fiziksel ayar düğmesi veya çerçeve kullanırken tutarlı bir deneyim için RotaryScrollableDefaults.snapBehavior(columnState) öğesini kullanarak rotaryScrollableBehavior öğesini eşleşecek şekilde ayarlayın.

val columnState = rememberTransformingLazyColumnState()
ScreenScaffold(scrollState = columnState) {
    TransformingLazyColumn(
        state = columnState,
        flingBehavior = TransformingLazyColumnDefaults.snapFlingBehavior(columnState),
        rotaryScrollableBehavior = RotaryScrollableDefaults.snapBehavior(columnState)
    ) {
        // ...
        // ...
    }
}

Ters düzen

Kaydırılabilir bir liste varsayılan olarak üst kenarına sabitlenir. Bir kullanıcı standart bir listenin en altına kaydırdıktan sonra listenin sonuna yeni bir öğe eklenirse liste, kullanıcının mevcut öğe görünümünü korur. Örneğin, kullanıcı ekranın alt kısmındaki 10. öğeyi görüntülerken 11. öğe eklenirse görünüm 10. öğeye odaklanmaya devam eder ve 11. öğe, geçerli görünümün altında ekran dışında görünür.

Mesajlaşma uygulamaları veya canlı günlükler gibi kullanım alanlarında bu davranış genellikle istenmez. Yeni öğeler geldiğinde, listenin en altında olan kullanıcılar genellikle en son içeriği hemen görmek ister. Birçok öğe aynı anda gelirse listede en son öğe en altta gösterilir (yani kullanıcı yukarı kaydırmadığı sürece bazı ara öğeler hiç gösterilmeyebilir).

Bu kullanım alanlarını desteklemek için TransformingLazyColumn, reverseLayout = true ayarını yaparak düzeni tersine çevirmenize olanak tanır. Bu işlem, listenin bağlantı noktasını üst kenardan alt kenara değiştirir.

Kolaylık sağlamak için reverseLayout = true ayarı, öğelerin görsel sırasını ve kaydırma hareketlerinin yönünü de tersine çevirir:

  • Öğeler alttan üste doğru oluşturulur. Yani 0 dizini ekranın en altında görünür.
  • Yukarı kaydırdığınızda daha yüksek dizinlere sahip öğeler gösterilir.

Ters düzenle birlikte tutturup fırlatma davranışı eklemek için aşağıdaki snippet'te gösterildiği gibi flingBehavior ve rotaryScrollableBehavior öğelerini birleştirebilirsiniz:

val columnState = rememberTransformingLazyColumnState()
val transformationSpec = rememberTransformationSpec()
ScreenScaffold(scrollState = columnState) { contentPadding ->
    TransformingLazyColumn(
        state = columnState,
        contentPadding = contentPadding,
        reverseLayout = true,
        modifier = Modifier.fillMaxWidth()
    ) {
        items(10) { index ->
            Button(
                label = {
                    Text(
                        text = "Item ${index + 1}"
                    )
                },
                onClick = {},
                modifier = Modifier
                    .fillMaxWidth()
                    .transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(ButtonDefaults.minimumVerticalListContentPadding),
                transformation = SurfaceTransformation(transformationSpec)
            )
        }
        item {
            // With reverseLayout = true, the last item declared appears at the top.
            ListHeader(
                modifier = Modifier
                    .fillMaxWidth()
                    .transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(ListHeaderDefaults.minimumTopListContentPadding),
                transformation = SurfaceTransformation(transformationSpec)
            ) {
                Text("Header")
            }
        }
    }
}

Aşağıdaki resimlerde normal liste ile ters liste arasındaki fark gösterilmektedir:

Normal düzene sahip bir TransformingLazyColumn. En üstte 1. öğe, diğer öğeler ise artan sırada gösteriliyor.
Şekil 1. İçeriğin yukarıdan aşağıya doğru doldurulduğu standart bir liste düzeni.
Ters düzene sahip bir TransformingLazyColumn. Öğeler, en altta 1. öğe olacak şekilde yukarı doğru azalan sırada gösteriliyor.
Şekil 2. İçeriğin alttan üste doğru doldurulduğu ters liste düzeni.