Liste ayrıntısı düzeni oluşturma

Liste-ayrıntı düzeni, bir bölmenin öğe listesini, diğer bölmenin ise listeden seçilen öğelerin ayrıntılarını gösterdiği çift bölmeli bir düzenden oluşan kullanıcı arayüzü kalıbıdır.

Bu kalıp, özellikle büyük koleksiyonların öğeleri hakkında ayrıntılı bilgi sağlayan uygulamalar için kullanışlıdır. Örneğin, e-posta listesi ve her e-posta iletisinin ayrıntılı içeriğini içeren bir e-posta istemcisi. Liste-ayrıntı düzeni, uygulama tercihlerini bir kategori listesine bölmek ve her kategorinin tercihlerini Ayrıntı penceresinde göstermek gibi daha az kritik yollar için de kullanılabilir.

Liste sayfasının yanında gösterilen ayrıntı penceresi.
Şekil 1. Yeterli ekran boyutu mevcut olduğunda ayrıntı bölmesi, liste bölmesinin yanında gösterilir.
Bir öğe seçildikten sonra ayrıntı penceresi tüm ekranı kaplar.
Şekil 2. Ekran boyutu sınırlı olduğunda ayrıntı penceresi (bir öğe seçildiğinden) tüm alanı kaplar.

NavigableListDetailPaneScaffold ile liste-ayrıntı düzenini uygulama

NavigableListDetailPaneScaffold, Jetpack Compose'da liste-ayrıntı düzeninin uygulanmasını kolaylaştıran bir composable'dır. ListDetailPaneScaffold öğesini sarmalar ve yerleşik gezinme ile tahmin edilen geri gitme animasyonları ekler.

Liste-ayrıntı düzeni iskeleleri en fazla üç bölmeyi destekler:

  1. Liste bölmesi: Bir öğe koleksiyonu gösterir.
  2. Ayrıntı penceresi: Seçili öğenin ayrıntılarını gösterir.
  3. Ek panel (isteğe bağlı): Gerektiğinde ek bağlam bilgisi sağlar.

İskelet, pencere boyutuna göre uyarlanır:

  • Büyük pencerelerde liste ve ayrıntı penceresi bölmeleri yan yana görünür.
  • Küçük pencerelerde, kullanıcılar gezinirken geçiş yaparak aynı anda yalnızca bir bölme görünür.

Bağımlılıkları bildirme

NavigableListDetailPaneScaffold, Material 3 uyarlanabilir gezinme kitaplığının bir parçasıdır.

Uygulamanızın veya modülünüzün build.gradle dosyasına aşağıdaki üç ilgili bağımlılığı ekleyin:

Kotlin

implementation("androidx.compose.material3.adaptive:adaptive")
implementation("androidx.compose.material3.adaptive:adaptive-layout")
implementation("androidx.compose.material3.adaptive:adaptive-navigation")

Modern

implementation 'androidx.compose.material3.adaptive:adaptive'
implementation 'androidx.compose.material3.adaptive:adaptive-layout'
implementation 'androidx.compose.material3.adaptive:adaptive-navigation'
  • adaptive: HingeInfo ve Posture gibi alt düzey yapı taşları
  • adaptive-layout: ListDetailPaneScaffold ve SupportingPaneScaffold gibi uyarlanabilir düzenler
  • adaptive-navigation: Bölmeler içinde ve arasında gezinmek için composable'lar ve varsayılan olarak gezinmeyi destekleyen uyarlanabilir düzenler (ör. NavigableListDetailPaneScaffold ve NavigableSupportingPaneScaffold)

Projenizin compose-material3-adaptive sürüm 1.1.0-beta1 veya sonraki bir sürümü içerdiğinden emin olun.

Tahmin edilen geri gitme hareketini etkinleştirme

Android 15 veya önceki sürümlerde tahmin edilen geri gitme animasyonlarını etkinleştirmek için tahmin edilen geri gitme hareketini desteklemeyi kabul etmeniz gerekir. Bu özelliği etkinleştirmek için AndroidManifest.xml dosyanızdaki <application> etiketine veya <activity> etiketlerine android:enableOnBackInvokedCallback="true" ekleyin. Daha fazla bilgi için Tahmin edilen geri gitme hareketini etkinleştirme başlıklı makaleyi inceleyin.

Uygulamanız Android 16'yı (API düzeyi 36) veya sonraki sürümleri hedeflediğinde tahmin edilen geri gitme özelliği varsayılan olarak etkinleştirilir.

Temel kullanım

NavigableListDetailPaneScaffold'i aşağıdaki gibi uygulayın:

  1. Seçilen içeriği temsil eden bir sınıf kullanın. Seçilen liste öğesinin kaydedilmesini ve geri yüklenmesini desteklemek için Parcelable sınıfını kullanın. Kodu sizin için oluşturması için kotlin-parcelize eklentisini kullanın.
  2. rememberListDetailPaneScaffoldNavigator ile ThreePaneScaffoldNavigator oluşturun.

Bu gezinme aracı; liste, ayrıntı ve ekstra bölmeler arasında geçiş yapmak için kullanılır. Genel bir tür bildirerek gezinme aracı, iskelenin durumunu da (yani hangi MyItem öğesinin gösterildiğini) izler. Bu tür, Parcelable olduğundan durum, yapılandırma değişikliklerini otomatik olarak işlemek için gezinme aracı tarafından kaydedilip geri yüklenebilir.

  1. Gezgini NavigableListDetailPaneScaffold composable'a iletin.

  2. Liste bölmesi uygulamanızı NavigableListDetailPaneScaffold öğesine sağlayın. Gezinme sırasında varsayılan bölme animasyonlarını uygulamak için AnimatedPane kodunu kullanın. Ardından ThreePaneScaffoldNavigator tuşunu kullanarak ayrıntı penceresine (ListDetailPaneScaffoldRole.Detail) gidin ve başarılı olan öğeyi görüntüleyin.

  3. Ayrıntı penceresi uygulamanızı NavigableListDetailPaneScaffold dosyasına ekleyin.

Gezinme tamamlandığında currentDestination, uygulamanızın gittiği bölmeyi (bölmede gösterilen içerik dahil) içerir. contentKey özelliği, orijinal çağrıda belirtilen türle aynıdır. Bu sayede, görüntülemeniz gereken tüm verilere erişebilirsiniz.

  1. Dilerseniz NavigableListDetailPaneScaffold içindeki defaultBackBehavior değerini değiştirebilirsiniz. Varsayılan olarak NavigableListDetailPaneScaffold, defaultBackBehavior için PopUntilScaffoldValueChange kullanır.

Uygulamanız farklı bir geri gezinme kalıbı gerektiriyorsa başka bir BackNavigationBehavior seçeneği belirterek bu davranışı geçersiz kılabilirsiniz.

BackNavigationBehavior seçenek

Aşağıdaki bölümde, bir bölmesinde e-posta listesi, diğer bölmesinde ise ayrıntılı görünüm bulunan bir e-posta uygulaması örneği kullanılmıştır.

Bu davranış, genel düzen yapısındaki değişikliklere odaklanır. Çok bölmeli bir düzende, ayrıntı penceresindeki e-posta içeriğini değiştirmek temel düzen yapısını değiştirmez. Bu nedenle, geri düğmesi uygulamadan veya mevcut gezinme grafiğinden çıkabilir. Çünkü mevcut bağlamda geri dönülecek bir düzen değişikliği yoktur. Tek bölmeli bir düzende geri düğmesine basıldığında, ayrıntı görünümündeki içerik değişiklikleri atlanır ve liste görünümüne dönülür. Bu, net bir düzen değişikliği anlamına gelir.

Aşağıdaki örnekleri inceleyin:

  • Çoklu Bölme: Ayrıntı penceresinde bir e-postayı (1. Öğe) görüntülüyorsunuz. Başka bir e-postayı (2. öğe) tıkladığınızda ayrıntı penceresi güncellenir ancak liste ve ayrıntı pencereleri görünür kalır. Geri düğmesine basıldığında uygulamadan veya mevcut gezinme akışından çıkılabilir.
  • Tek bölme: 1. öğeyi, ardından 2. öğeyi görüntülersiniz. Geri düğmesine bastığınızda doğrudan e-posta listesi bölmesine dönersiniz.

Kullanıcıların her geri işleminde farklı düzen geçişleri algılamasını istediğinizde bunu kullanın.

Farklı düzen bölmelerinde gezinme değeri değişikliklerini gösteren görsel.
PopUntilContentChange

Bu davranış, görüntülenen içeriğe öncelik verir. Öğe 1'i ve ardından Öğe 2'yi görüntülerseniz geri düğmesine bastığınızda düzenden bağımsız olarak Öğe 1'e geri dönersiniz.

Aşağıdaki örnekleri inceleyin:

  • Çoklu Bölme: Ayrıntı penceresinde 1. öğeyi görüntüler, ardından listedeki 2. öğeyi tıklarsınız. Ayrıntı penceresi güncellenir. Geri düğmesine basıldığında ayrıntı penceresi 1. öğeye geri döner.
  • Tek bölme: Aynı içerik geri döndürme işlemi gerçekleşir.

Kullanıcınız geri işlemiyle daha önce görüntülenen içeriğe dönmeyi beklediğinde bunu kullanın.

iki ayrıntı penceresi arasındaki geçiş
PopUntilCurrentDestinationChange

Bu davranış, mevcut gezinme hedefi değişene kadar eski yığını açar. Bu durum, tek ve çok bölmeli düzenler için de geçerlidir.

Aşağıdaki örnekleri inceleyin:

Tek veya çok bölmeli bir düzende olmanız fark etmeksizin geri düğmesine bastığınızda odak, vurgulanan gezinme öğesinden önceki hedefe taşınır. E-posta uygulamamızda bu, seçili bölmenin görsel göstergesinin değişeceği anlamına gelir.

Geçerli gezinme işleminin net bir görsel göstergesini korumanın kullanıcı deneyimi açısından çok önemli olduğu durumlarda bu seçeneği kullanın.

ayrıntı ve liste bölmeleri arasında gezinme
PopLatest

Bu seçenek, yalnızca en son hedefi geri yığınından kaldırır. Ara durumları atlamadan geri gezinme için bu seçeneği kullanın.

Bu adımları uyguladıktan sonra kodunuz aşağıdakine benzer:

NavigableListDetailPaneScaffold(
    navigator = navigator,
    listPane = {
        AnimatedPane {
            ListContent(
                words = sampleWords,
                selectionState = navigator.currentDestination?.contentKey?.let {
                    SelectionVisibilityState.ShowSelection(it)
                } ?: SelectionVisibilityState.NoSelection,
                onWordClick = { word ->
                    scope.launch {
                        navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, word)
                    }
                },
                animatedVisibilityScope = this@AnimatedPane,
                sharedTransitionScope = this@SharedTransitionLayout
            )
        }
    },
    detailPane = {
        AnimatedPane {
            DetailContent(
                definedWord = navigator.currentDestination?.contentKey,
                animatedVisibilityScope = this@AnimatedPane,
                sharedTransitionScope = this@SharedTransitionLayout,
                onClosePane = {
                    scope.launch {
                        navigator.navigateBack(
                            backNavigationBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange
                        )

                    }
                }
            )
        }
    }