Uyarlanabilir gezinme oluşturma

Çoğu uygulamanın, uygulamanın birincil gezinme kullanıcı arayüzü üzerinden erişilebilen birkaç üst düzey hedefi vardır. Standart telefon ekranı gibi kompakt pencerelerde hedefler genellikle pencerenin alt kısmındaki gezinme çubuğunda gösterilir. Tabletteki tam ekran uygulama gibi genişletilmiş bir pencerede, cihazın sol ve sağ taraflarını tutarken gezinme denetimlerine daha kolay erişilebildiğinden, uygulamanın yanında bir gezinme çubuğu genellikle daha iyi bir seçimdir.

NavigationSuiteScaffold, WindowSizeClass'e göre uygun gezinme kullanıcı arayüzü bileşenini görüntüleyerek gezinme kullanıcı arayüzleri arasında geçiş yapmayı kolaylaştırır. Bu, çalışma zamanı pencere boyutu değişiklikleri sırasında kullanıcı arayüzünü dinamik olarak değiştirmeyi içerir. Varsayılan davranış, aşağıdaki kullanıcı arayüzü bileşenlerinden birini göstermektir:

  • Genişlik veya yükseklik kompaktsa ya da cihaz masaüstü modundaysa gezinme çubuğu
  • Diğer her şey için gezinme çubuğu
Şekil 1. NavigationSuiteScaffold, kompakt pencerelerde bir gezinme çubuğu gösterir.
Şekil 2. NavigationSuiteScaffold, genişletilmiş pencerelerde bir gezinme çubuğu gösterir.

Bağımlılık ekleme

NavigationSuiteScaffold, Material3 uyarlanabilir gezinme paketi kitaplığının bir parçasıdır. Uygulamanızın veya modülünüzün build.gradle dosyasına kitaplık için bir bağımlılık ekleyin:

Kotlin

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

Groovy

implementation 'androidx.compose.material3:material3-adaptive-navigation-suite'

İskele oluşturma

NavigationSuiteScaffold'ün iki ana bölümü, gezinme paketi öğeleri ve seçilen hedefin içeriğidir. Gezinme paketi öğelerini doğrudan bir bileşende tanımlayabilirsiniz ancak bunların başka bir yerde (ör. bir enum'da) tanımlanması yaygındır:

enum class AppDestinations(
    @StringRes val label: Int,
    val icon: ImageVector,
    @StringRes val contentDescription: Int
) {
    HOME(R.string.home, Icons.Default.Home, R.string.home),
    FAVORITES(R.string.favorites, Icons.Default.Favorite, R.string.favorites),
    SHOPPING(R.string.shopping, Icons.Default.ShoppingCart, R.string.shopping),
    PROFILE(R.string.profile, Icons.Default.AccountBox, R.string.profile),
}

NavigationSuiteScaffold'ü kullanmak için mevcut hedefi izlemeniz gerekir. Bunu rememberSaveable'ü kullanarak yapabilirsiniz:

var currentDestination by rememberSaveable { mutableStateOf(AppDestinations.HOME) }

Aşağıdaki örnekte, navigationSuiteItems parametresi (tür NavigationSuiteScope) tek bir hedef için gezinme kullanıcı arayüzünü tanımlamak üzere item işlevini kullanır. Hedef kullanıcı arayüzü, gezinme çubukları, raylar ve çekmecelerde kullanılır. Gezinme öğeleri oluşturmak için AppDestinations (önceki snippet'te tanımlanmıştır) öğenizi döngüye alırsınız:

NavigationSuiteScaffold(
    navigationSuiteItems = {
        AppDestinations.entries.forEach {
            item(
                icon = {
                    Icon(
                        it.icon,
                        contentDescription = stringResource(it.contentDescription)
                    )
                },
                label = { Text(stringResource(it.label)) },
                selected = it == currentDestination,
                onClick = { currentDestination = it }
            )
        }
    }
) {
    // TODO: Destination content.
}

Hedef içerik lambda'sında, hangi kullanıcı arayüzünün gösterileceğine karar vermek için currentDestination değerini kullanın. Uygulamanızda bir gezinme kitaplığı kullanıyorsanız uygun hedefi görüntülemek için burada kullanın. Bir when ifadesi yeterli olabilir:

NavigationSuiteScaffold(
    navigationSuiteItems = { /*...*/ }
) {
    // Destination content.
    when (currentDestination) {
        AppDestinations.HOME -> HomeDestination()
        AppDestinations.FAVORITES -> FavoritesDestination()
        AppDestinations.SHOPPING -> ShoppingDestination()
        AppDestinations.PROFILE -> ProfileDestination()
    }
}

Renkleri değiştir

NavigationSuiteScaffold, iskelenin kapladığı tüm alan (genellikle pencerenin tamamı) üzerinde bir Surface oluşturur. Ayrıca, iskelet NavigationBar gibi belirli bir gezinme kullanıcı arayüzünü çizer. Hem yüzey hem de gezinme kullanıcı arayüzü, uygulamanızın temasında belirtilen değerleri kullanır ancak tema değerlerini geçersiz kılabilirsiniz.

containerColor parametresi, yüzeyin rengini belirtir. Varsayılan olarak, renk şemanızın arka plan rengi kullanılır. contentColor parametresi, söz konusu yüzeydeki içeriğin rengini belirtir. Varsayılan olarak, containerColor için belirtilen "açık" renk kullanılır. Örneğin, containerColor background rengini kullanıyorsa contentColor onBackground rengini kullanır. Renk sisteminin işleyiş şekli hakkında daha fazla bilgi için Oluştur'da Materyal Tasarım 3 tema oluşturma başlıklı makaleyi inceleyin. Bu değerleri geçersiz kılarken uygulamanızın koyu ve açık ekran modlarını desteklemesi için temanızda tanımlanan değerleri kullanın:

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    containerColor = MaterialTheme.colorScheme.primary,
    contentColor = MaterialTheme.colorScheme.onPrimary,
) {
    // Content...
}

Gezinme kullanıcı arayüzü, NavigationSuiteScaffold yüzeyinin önüne çizilir. Kullanıcı arayüzü renklerinin varsayılan değerleri NavigationSuiteDefaults.colors() tarafından sağlanır ancak bu değerleri de geçersiz kılabilirsiniz. Örneğin, gezinme çubuğunun arka planının şeffaf olmasını ancak diğer değerlerin varsayılan değerleri olmasını istiyorsanız navigationBarContainerColor parametresini geçersiz kılın:

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    navigationSuiteColors = NavigationSuiteDefaults.colors(
        navigationBarContainerColor = Color.Transparent,
    )
) {
    // Content...
}

Son olarak, gezinme kullanıcı arayüzündeki her öğeyi özelleştirebilirsiniz. item işlevini çağırırken NavigationSuiteItemColors örneğini iletebilirsiniz. Sınıf, gezinme çubuğu, gezinme çubuğu rayı ve gezinme çekmecesinde bulunan öğelerin renklerini belirtir. Yani her gezinme kullanıcı arayüzü türünde aynı renkleri kullanabilir veya renkleri ihtiyaçlarınıza göre değiştirebilirsiniz. Tüm öğeler için aynı nesne örneğini kullanmak üzere NavigationSuiteScaffold düzeyinde renkleri tanımlayın ve yalnızca değiştirmek istediğiniz renkleri geçersiz kılmak için NavigationSuiteDefaults.itemColors() işlevini çağırın:

val myNavigationSuiteItemColors = NavigationSuiteDefaults.itemColors(
    navigationBarItemColors = NavigationBarItemDefaults.colors(
        indicatorColor = MaterialTheme.colorScheme.primaryContainer,
        selectedIconColor = MaterialTheme.colorScheme.onPrimaryContainer
    ),
)

NavigationSuiteScaffold(
    navigationSuiteItems = {
        AppDestinations.entries.forEach {
            item(
                icon = {
                    Icon(
                        it.icon,
                        contentDescription = stringResource(it.contentDescription)
                    )
                },
                label = { Text(stringResource(it.label)) },
                selected = it == currentDestination,
                onClick = { currentDestination = it },
                colors = myNavigationSuiteItemColors,
            )
        }
    },
) {
    // Content...
}

Gezinme türlerini özelleştirme

NavigationSuiteScaffold'ün varsayılan davranışı, gezinme kullanıcı arayüzünü pencere boyutu sınıflarına göre değiştirir. Ancak bu davranışı geçersiz kılmak isteyebilirsiniz. Örneğin, uygulamanız bir feed için tek bir büyük içerik bölmesi gösteriyorsa genişletilmiş pencereler için kalıcı bir gezinme çekmecesi kullanabilir ancak kompakt ve orta pencere boyutu sınıfları için varsayılan davranışa geri dönebilir:

val adaptiveInfo = currentWindowAdaptiveInfo()
val customNavSuiteType = with(adaptiveInfo) {
    if (windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.EXPANDED) {
        NavigationSuiteType.NavigationDrawer
    } else {
        NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo(adaptiveInfo)
    }
}

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    layoutType = customNavSuiteType,
) {
    // Content...
}

Ek kaynaklar