Destekleyici bölme düzeni oluşturma

Destekleyici bölme düzeni, kullanıcının odak noktasını uygulamanın ana içeriğinde tutarken alakalı destekleyici bilgileri gösterir. Örneğin, ana bölmede bir filmle ilgili ayrıntılar gösterilirken destekleyici bölmede benzer filmler, aynı yönetmenin filmleri veya aynı oyuncuların yer aldığı yapımlar listelenebilir.

Daha fazla bilgi için Material 3 destek bölmesi yönergeleri başlıklı makaleyi inceleyin.

İskele ile destekleyici bir bölme uygulama

NavigableSupportingPaneScaffold, Jetpack Compose'da destekleyici bölme düzeninin uygulanmasını kolaylaştıran bir composable'dır. Bu, SupportingPaneScaffold öğesini sarmalar ve yerleşik gezinme ile tahmin edilen geri gitme işleme özelliğini ekler.

Destekleyici bir bölme iskeleti en fazla üç bölmeyi destekler:

  • Ana bölme: Birincil içeriği gösterir.
  • Destek bölmesi: Ana bölmeyle ilgili ek bağlam veya araçlar sağlar.
  • Ek bölme (isteğe bağlı): Gerekli olduğunda ek içerik için kullanılır.

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

  • Büyük pencerelerde ana ve destekleyici paneller yan yana görünür.
  • Küçük pencerelerde, kullanıcılar gezinirken yalnızca bir bölme görünür.

    Destekleyici içeriklerin yanında, ekranın büyük bir bölümünü kaplayan ana içerik.
    Şekil 1. Destek bölmesi düzeni.

Bağımlılık ekleme

NavigableSupportingPaneScaffold, Material 3 uyarlanabilir düzen kitaplığının bir parçasıdır.

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

Kotlin

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

Groovy

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 düşük seviyeli yapı taşları

  • adaptive-layout: ListDetailPaneScaffold ve SupportingPaneScaffold gibi uyarlanabilir düzenler

  • adaptive-navigation: Paneller arasında ve paneller içinde gezinmeye yönelik composable'lar ile varsayılan olarak gezinmeyi destekleyen uyarlanabilir düzenler (ör. NavigableListDetailPaneScaffold ve NavigableSupportingPaneScaffold)

Projenizin compose-material3-adaptive 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 tahmine dayalı geri animasyonlarını etkinleştirmek için tahmine dayalı geri hareketini desteklemeyi kabul etmeniz gerekir. Bu özelliği etkinleştirmek için <application> etiketine veya AndroidManifest.xml dosyanızdaki tek tek <activity> etiketlerine android:enableOnBackInvokedCallback="true" ekleyin.

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

Gezinme paneli oluşturma

Küçük pencerelerde aynı anda yalnızca bir bölme gösterilir. Bu nedenle, bölmeler arasında geçiş yapmak için ThreePaneScaffoldNavigator tuşunu kullanın. rememberSupportingPaneScaffoldNavigator ile gezinme öğesinin bir örneğini oluşturun.

val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator()
val scope = rememberCoroutineScope()

Gezgini iskeleye iletin.

İskele için iskelenin durumunu, ThreePaneScaffoldValue ve PaneScaffoldDirective temsil eden bir arayüz olan ThreePaneScaffoldNavigator gerekir.

NavigableSupportingPaneScaffold(
    navigator = scaffoldNavigator,
    mainPane = { /*...*/ },
    supportingPane = { /*...*/ },
)

Ana bölme ve destekleyici bölme, içeriğinizi içeren composable'lardır. Gezinme sırasında varsayılan bölme animasyonlarını uygulamak için AnimatedPane simgesini kullanın. Destekleyici bölmenin gizli olup olmadığını kontrol etmek için iskele değerini kullanın. Gizliyse destekleyici bölmeyi göstermek için navigateTo(SupportingPaneScaffoldRole.Supporting) işlevini çağıran bir düğme gösterin.

Büyük ekranlarda, destekleyici bölmeyi kapatmak için ThreePaneScaffoldNavigator.navigateBack() yöntemini kullanın ve BackNavigationBehavior.PopUntilScaffoldValueChange sabitini iletin. Bu yöntemin çağrılması, NavigableSupportingPaneScaffold öğesinin yeniden oluşturulmasını zorlar. Yeniden oluşturma sırasında, destekleyici bölmenin gösterilip gösterilmeyeceğini belirlemek için ThreePaneScaffoldNavigator.currentDestination özelliğini kontrol edin.

İskele için eksiksiz bir uygulama aşağıda verilmiştir:

val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator()
val scope = rememberCoroutineScope()
val backNavigationBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange

NavigableSupportingPaneScaffold(
    navigator = scaffoldNavigator,
    mainPane = {
        AnimatedPane(
            modifier = Modifier
                .safeContentPadding()
                .background(Color.Red)
        ) {
            if (scaffoldNavigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Hidden) {
                Button(
                    modifier = Modifier
                        .wrapContentSize(),
                    onClick = {
                        scope.launch {
                            scaffoldNavigator.navigateTo(SupportingPaneScaffoldRole.Supporting)
                        }
                    }
                ) {
                    Text("Show supporting pane")
                }
            } else {
                Text("Supporting pane is shown")
            }
        }
    },
    supportingPane = {
        AnimatedPane(modifier = Modifier.safeContentPadding()) {
            Column {
                // Allow users to dismiss the supporting pane. Use back navigation to
                // hide an expanded supporting pane.
                if (scaffoldNavigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Expanded) {
                    // Material design principles promote the usage of a right-aligned
                    // close (X) button.
                    IconButton(
                        modifier =  Modifier.align(Alignment.End).padding(16.dp),
                        onClick = {
                            scope.launch {
                                scaffoldNavigator.navigateBack(backNavigationBehavior)
                            }
                        }
                    ) {
                        Icon(Icons.Default.Close, contentDescription = "Close")
                    }
                }
                Text("Supporting pane")
            }

        }
    }
)

Bölme composable'larını ayıklama

SupportingPaneScaffold öğesinin her bir bölmesini, yeniden kullanılabilir ve test edilebilir hale getirmek için kendi composable'larına ayırın. Varsayılan animasyonları kullanmak istiyorsanız ThreePaneScaffoldScope ile AnimatedPane'e erişin:

@OptIn(ExperimentalMaterial3AdaptiveApi::class)
@Composable
fun ThreePaneScaffoldPaneScope.MainPane(
    shouldShowSupportingPaneButton: Boolean,
    onNavigateToSupportingPane: () -> Unit,
    modifier: Modifier = Modifier,
) {
    AnimatedPane(
        modifier = modifier.safeContentPadding()
    ) {
        // Main pane content
        if (shouldShowSupportingPaneButton) {
            Button(onClick = onNavigateToSupportingPane) {
                Text("Show supporting pane")
            }
        } else {
            Text("Supporting pane is shown")
        }
    }
}

@OptIn(ExperimentalMaterial3AdaptiveApi::class)
@Composable
fun ThreePaneScaffoldPaneScope.SupportingPane(
    scaffoldNavigator: ThreePaneScaffoldNavigator<Any>,
    modifier: Modifier = Modifier,
    backNavigationBehavior: BackNavigationBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange,
) {
    val scope = rememberCoroutineScope()
    AnimatedPane(modifier = Modifier.safeContentPadding()) {
        Column {
            // Allow users to dismiss the supporting pane. Use back navigation to
            // hide an expanded supporting pane.
            if (scaffoldNavigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Expanded) {
                // Material design principles promote the usage of a right-aligned
                // close (X) button.
                IconButton(
                    modifier =  modifier.align(Alignment.End).padding(16.dp),
                    onClick = {
                        scope.launch {
                            scaffoldNavigator.navigateBack(backNavigationBehavior)
                        }
                    }
                ) {
                    Icon(Icons.Default.Close, contentDescription = "Close")
                }
            }
            Text("Supporting pane")
        }

    }
}

Panelleri composable'lara ayırmak, SupportingPaneScaffold kullanımını kolaylaştırır (aşağıdakileri, önceki bölümdeki iskelenin tam uygulamasıyla karşılaştırın):

val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator()
val scope = rememberCoroutineScope()

NavigableSupportingPaneScaffold(
    navigator = scaffoldNavigator,
    mainPane = {
        MainPane(
            shouldShowSupportingPaneButton = scaffoldNavigator.scaffoldValue.secondary == PaneAdaptedValue.Hidden,
            onNavigateToSupportingPane = {
                scope.launch {
                    scaffoldNavigator.navigateTo(ThreePaneScaffoldRole.Secondary)
                }
            }
        )
    },
    supportingPane = { SupportingPane(scaffoldNavigator = scaffoldNavigator) },
)

İskeleyle ilgili belirli yönler üzerinde daha fazla kontrole ihtiyacınız varsa NavigableSupportingPaneScaffold yerine SupportingPaneScaffold kullanmayı deneyin. Bu, PaneScaffoldDirective ve ThreePaneScaffoldValue veya ThreePaneScaffoldState öğelerini ayrı ayrı kabul eder. Bu esneklik, bölme aralığı için özel mantık uygulamanıza ve aynı anda kaç bölmenin gösterilmesi gerektiğine karar vermenize olanak tanır. Ayrıca ThreePaneScaffoldPredictiveBackHandler ekleyerek tahmin edilen geri gitme desteğini etkinleştirebilirsiniz.

ThreePaneScaffoldPredictiveBackHandler ekle

İskele Navigator örneğini alan ve backBehavior değerini belirten tahmin edilen geri gitme işleyicisini ekleyin. Bu, geri gezinme sırasında hedeflerin arka yığından nasıl çıkarılacağını belirler. Ardından scaffoldDirective ve scaffoldState ile SupportingPaneScaffold'ye gidin. ThreePaneScaffoldState kabul eden aşırı yüklemeyi kullanın ve scaffoldNavigator.scaffoldState değerini iletin.

SupportingPaneScaffold içindeki ana ve destekleyici bölmeleri tanımlayın. Varsayılan bölme animasyonları için AnimatedPane kullanın.

Bu adımları uyguladıktan sonra kodunuz aşağıdaki gibi görünmelidir:

val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator()
val scope = rememberCoroutineScope()

ThreePaneScaffoldPredictiveBackHandler(
    navigator = scaffoldNavigator,
    backBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange
)

SupportingPaneScaffold(
    directive = scaffoldNavigator.scaffoldDirective,
    scaffoldState = scaffoldNavigator.scaffoldState,
    mainPane = {
        MainPane(
            shouldShowSupportingPaneButton = scaffoldNavigator.scaffoldValue.secondary == PaneAdaptedValue.Hidden,
            onNavigateToSupportingPane = {
                scope.launch {
                    scaffoldNavigator.navigateTo(ThreePaneScaffoldRole.Secondary)
                }
            }
        )
    },
    supportingPane = { SupportingPane(scaffoldNavigator = scaffoldNavigator) },
)