Gezinme bileşeni, Kotlin tabanlı alana özgü bir dil sağlar veya
DSL, Kotlin'in
type-safe derleyiciler oluşturun.
Bu API, grafiğinizi Kotlin kodunuzda bildirimli bir şekilde oluşturmanıza olanak tanır.
bir XML kaynağı kullanmaktır. Bu, bir proje başlatma belgesi için
gezinmeyi kolaylaştırır. Örneğin, uygulamanız
harici bir web hizmetinden gezinme yapılandırmasını önbelleğe almak ve ardından
dinamik olarak bir gezinme grafiği oluşturmak için bu yapılandırmayı
onCreate()
işlevi.
Bağımlılıklar
Kotlin DSL'yi kullanmak için aşağıdaki bağımlılığı uygulamanızın
build.gradle
dosyası:
Eski
dependencies { def nav_version = "2.7.7" api "androidx.navigation:navigation-fragment-ktx:$nav_version" }
Kotlin
dependencies { val nav_version = "2.7.7" api("androidx.navigation:navigation-fragment-ktx:$nav_version") }
Grafik oluşturma
Temel bir örnekle,
Sunflower uygulaması. Bunun için
Örneğin, iki hedefimiz var: home
ve plant_detail
. home
Hedef, kullanıcı uygulamayı ilk kez başlattığında mevcuttur. Bu hedef
kullanıcının bahçesindeki bitkilerin bir listesini görüntüler. Kullanıcı
bitkiler olduğunda uygulama plant_detail
hedefine gidiyor.
Şekil 1'de bu hedefler,
Uygulamanın kullandığı plant_detail
hedef ve bir işlem (to_plant_detail
)
home
- plant_detail
arası rotayı izleyin.
Kotlin DSL Nav Grafiği Barındırma
Uygulamanızın gezinme grafiğini oluşturabilmeniz için öncelikle
görebilirsiniz. Bu örnekte parçalar kullanıldığı için, grafiği
NavHostFragment
bir
FragmentContainerView
:
<!-- activity_garden.xml -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true" />
</FrameLayout>
Bu örnekte app:navGraph
özelliğinin ayarlanmadığına dikkat edin. Grafik
bir
kaynak
res/navigation
klasörü olduğundan onCreate()
öğesinin bir parçası olarak ayarlanması gerekir
bu etkinliği takip etmeniz gerekir.
XML'de, bir işlem hedef kimliğini bir veya daha fazla bağımsız değişkenle birbirine bağlar. Bununla birlikte, Navigasyon DSL'sini kullanırken bir rota, görebilirsiniz. Yani DSL'yi kullanırken işlem kavramı yoktur.
Bir sonraki adım, görüntüleyebilirsiniz.
Grafiğiniz için sabit değerler oluşturun
XML tabanlı gezinme grafikleri
Android derleme işleminin bir parçası olarak ayrıştırılır. Sayısal bir sabit değer oluşturulur
(grafikte tanımlanan her id
özelliği için) Bu derleme zamanı, statik
Çalışma zamanında gezinme grafiğinizi oluştururken kimlikler kullanılamaz. Bu nedenle
Gezinme DSL'si, kimlikler yerine rota dizelerini kullanır. Her rota
benzersiz bir dizedir. Daha az veri almak için bunları sabit değer olarak tanımlamak,
risklerini tekrar gözden geçirelim.
Bağımsız argümanlar üzerinde çalışırken rota dizesinde yerleşik olarak bulunur. Rotada bu mantığı oluşturmak, proje boyunca çok sayıda yazım hatası oluşmuştur.
object nav_routes {
const val home = "home"
const val plant_detail = "plant_detail"
}
object nav_arguments {
const val plant_id = "plant_id"
const val plant_name = "plant_name"
}
NavGraphBuilder DSL ile grafik oluşturma
Sabit değerlerinizi tanımladıktan sonra, gezinme grafiğe dönüştürülebilir.
val navController = findNavController(R.id.nav_host_fragment)
navController.graph = navController.createGraph(
startDestination = nav_routes.home
) {
fragment<HomeFragment>(nav_routes.home) {
label = resources.getString(R.string.home_title)
}
fragment<PlantDetailFragment>("${nav_routes.plant_detail}/{${nav_arguments.plant_id}}") {
label = resources.getString(R.string.plant_detail_title)
argument(nav_arguments.plant_id) {
type = NavType.StringType
}
}
}
Bu örnekte, takip eden lambda
fragment()
DSL oluşturucu işlevi. Bu işlev, hedef için bir rota dizesi gerektiriyor
elde edilir. İşlev,
lambda ek yapılandırma için.
bağımsız değişkenler ve derin bağlantılar için yerleştirilmiş oluşturucu işlevleri.
Şu durumda olan Fragment
sınıfı
her hedefin kullanıcı arayüzünü, içeride parametreli bir tür olarak iletildiğini yönetir
açılı ayraçlar (<>
). Bu, android:name
öğesinin ayarlanmasıyla aynı etkiye sahiptir
özelliğini kullanmanızı öneririz.
Kotlin DSL grafiğinizle gezinme
Son olarak, standart URL'yi kullanarak home
konumundan plant_detail
konumuna gidebilirsiniz
NavController.Navigation()
şunu arar:
private fun navigateToPlant(plantId: String) {
findNavController().navigate("${nav_routes.plant_detail}/$plantId")
}
PlantDetailFragment
işlevinde, bağımsız değişkenin değerini aşağıda gösterildiği gibi alabilirsiniz:
aşağıdaki örnekte:
val plantId: String? = arguments?.getString(nav_arguments.plant_id)
Gezinme sırasında bağımsız değişkenlerin nasıl sağlanacağına ilişkin ayrıntıları hedef bağımsız değişkenler sağlama bölümüne bakın.
Bu kılavuzun geri kalanında, yaygın olarak kullanılan gezinme grafiği öğeleri, hedefler, bunları nasıl kullanacağınızı öğreneceksiniz.
Hedefler
Kotlin DSL, üç hedef türü için yerleşik destek sağlar:
Her biri kendine ait olan Fragment
, Activity
ve NavGraph
hedefleri
oluşturmak ve yapılandırmak için kullanılabilen satır içi uzantı işlevi
seçeceğiz.
Parça hedefleri
İlgili içeriği oluşturmak için kullanılan
fragment()
DSL işlevi, uygulayan parça sınıfına parametre haline getirilebilir ve
bu hedefe atanacak benzersiz rota dizesi ve ardından,
bölümünde açıklandığı gibi ek yapılandırma sağlayabilirsiniz.
Kotlin DSL grafiğinizle gezinme
bölümüne bakın.
fragment<FragmentDestination>(nav_routes.route_name) {
label = getString(R.string.fragment_title)
// arguments, deepLinks
}
Aktivite hedefi
activity()
DSL işlevi, bu hedefe atamak için benzersiz bir rota dizesi alır ancak
uygulanan herhangi bir etkinlik sınıfına parametre haline getirilmemiştir. Bunun yerine
sondaki lambda içinde isteğe bağlı activityClass
Bu esneklik sayesinde
implicit intent,
açıklamanız gerekmez. Parça hedeflerde olduğu gibi
Etiket, bağımsız değişkenler ve derin bağlantılar da yapılandırabilirsiniz.
activity(nav_routes.route_name) {
label = getString(R.string.activity_title)
// arguments, deepLinks...
activityClass = ActivityDestination::class
}
Navigasyon grafiğinin hedefi
navigation()
DSL işlevi,
iç içe yerleştirilmiş gezinme grafiği.
Bu işlev üç bağımsız değişken alır:
grafiğe, grafiğin başlangıç hedefinin rotasını ve
lambda'yı kullanarak grafiği daha fazla yapılandırın. Geçerli öğeler arasında diğer hedefler,
argümanları, derin bağlantıları ve
hedefe ilişkin açıklayıcı etiket.
Bu etiket, gezinme grafiğini kullanıcı arayüzüne bağlamak için yararlı olabilir
bileşenleri kullanarak
Gezinme Arayüzü
navigation("route_to_this_graph", nav_routes.home) {
// label, other destinations, deep links
}
Özel hedefleri destekleme
Bir
yeni hedef türünü
Kotlin DSL'yi doğrudan desteklemesi durumunda, bu hedefleri Kotlin'inize ekleyebilirsiniz
addDestination()
ile DSL:
// The NavigatorProvider is retrieved from the NavController
val customDestination = navigatorProvider[CustomNavigator::class].createDestination().apply {
route = Graph.CustomDestination.route
}
addDestination(customDestination)
Alternatif olarak, tekli artı operatörünü yeni bir oluşturulan hedefi grafiğe doğrudan ekleyin:
// The NavigatorProvider is retrieved from the NavController
+navigatorProvider[CustomNavigator::class].createDestination().apply {
route = Graph.CustomDestination.route
}
Hedef bağımsız değişkenleri sağlama
Herhangi bir hedef, isteğe bağlı veya gerekli bağımsız değişkenleri tanımlayabilir. Eylemler
kullanılarak tanımlanabilir
argument()
tüm etkinlikler için temel sınıf olan NavDestinationBuilder
üzerinde
hedef oluşturucu türleri. Bu işlev, bağımsız değişkenin adını bir dize olarak alır
oluşturmak ve yapılandırmak için kullanılan lambda
NavArgument
.
Lambda içinde bağımsız değişken veri türünü belirtebilirsiniz. Bu tür durumlarda varsayılan değer, geçerli ve null olup olmadığı gibi ayarlar.
fragment<PlantDetailFragment>("${nav_routes.plant_detail}/{${nav_arguments.plant_id}}") {
label = getString(R.string.plant_details_title)
argument(nav_arguments.plant_id) {
type = NavType.StringType
defaultValue = getString(R.string.default_plant_id)
nullable = true // default false
}
}
Bir defaultValue
sağlanırsa tür tahmin edilebilir. Hem defaultValue
hem de
ve bir type
sağlanmışsa türlerin eşleşmesi gerekir. Bkz.
Şu sorgu için NavType referans dokümanları:
mevcut bağımsız değişken türlerinin tam listesi.
Özel türler sağlama
Belirli türler, örneğin
ParcelableType
ve
SerializableType
,
rotalar veya derin bağlantılar tarafından kullanılan dizelerden değerlerin ayrıştırılmasını desteklemez.
Bunun nedeni, çalışma zamanında yansımaya dayalı olmamalarıdır. Bir özel rapor sağlayarak
NavType
sınıfını seçerseniz türünüzün bir rotadan tam olarak nasıl ayrıştırılacağını kontrol edebilirsiniz veya
derin bağlantı. Bu sayede
Kotlin Serileştirme veya diğer
kitaplıklarını kullanabilirsiniz.
Örneğin,
arama ekranı hem Serializable
(yeni bir URL parametresi sağlamak için)
kodlama/kod çözme desteği) ve Parcelize
(verilerin kaydedilmesini ve geri yüklenmesini desteklemek için
Bundle
üzerinden):
@Serializable
@Parcelize
data class SearchParameters(
val searchQuery: String,
val filters: List<String>
)
Özel NavType
şöyle yazılabilir:
val SearchParametersType = object : NavType<SearchParameters>(
isNullableAllowed = false
) {
override fun put(bundle: Bundle, key: String, value: SearchParameters) {
bundle.putParcelable(key, value)
}
override fun get(bundle: Bundle, key: String): SearchParameters {
return bundle.getParcelable(key) as SearchParameters
}
override fun serializeAsValue(value: SearchParameters): String {
// Serialized values must always be Uri encoded
return Uri.encode(Json.encodeToString(value))
}
override fun parseValue(value: String): SearchParameters {
// Navigation takes care of decoding the string
// before passing it to parseValue()
return Json.decodeFromString<SearchParameters>(value)
}
}
Bu, daha sonra Kotlin DSL'nizde diğer türler gibi kullanılabilir:
fragment<SearchFragment>(nav_routes.plant_search) {
label = getString(R.string.plant_search_title)
argument(nav_arguments.search_parameters) {
type = SearchParametersType
defaultValue = SearchParameters("cactus", emptyList())
}
}
NavType
, her bir alanın hem yazma hem de okuma sürecini içerir ve bu da
anlamına gelir. Bu, şuraya gittiğinizde de NavType
öğesinin kullanılması gerektiği anlamına gelir:
hedeften emin olmanız gerekir:
val params = SearchParameters("rose", listOf("available"))
val searchArgument = SearchParametersType.serializeAsValue(params)
navController.navigate("${nav_routes.plant_search}/$searchArgument")
Parametre, hedefteki bağımsız değişkenlerden edinilebilir:
val params: SearchParameters? = arguments?.getParcelable(nav_arguments.search_parameters)
Derin bağlantılar
Derin bağlantılar, XML ile desteklenen herhangi bir hedefe eklenebilir. gezinme grafiğidir. Bu belgede tanımlanan prosedürlerin hepsi, Bir hedef için derin bağlantı oluşturma proje yaşam döngüsü boyunca açık derin bağlantıyı kullanmak için Kotlin DSL.
Dolaylı derin bağlantı oluştururken
ancak o zaman hangisi için analiz edilebilecek bir XML gezinme kaynağınız yoksa
<deepLink>
öğeleri. Bu nedenle, <nav-graph>
öğesi; AndroidManifest.xml
dosyanıza
niyet filtrelerini manuel olarak etkinleştirin.
Sağladığınız amaç filtresi, temel URL modeli, işlemi ve
Uygulamanızın derin bağlantılarının mime türünü.
Her bir derin bağlantılı için daha spesifik bir deeplink
sağlayabilirsiniz
hedefini
deepLink()
DSL işlevi. Bu işlev, String
içeren bir NavDeepLink
kabul eder
URI modelini, intent işlemlerini temsil eden bir String
ve bir
mimeType'ı temsil eden String
.
Örnek:
deepLink {
uriPattern = "http://www.example.com/plants/"
action = "android.intent.action.MY_ACTION"
mimeType = "image/*"
}
Ekleyebileceğiniz derin bağlantı sayısıyla ilgili bir sınır yoktur. Her aradığınızda
deepLink()
o hedef için tutulan listeye yeni bir derin bağlantı eklenir.
Yol ve yol bilgilerini de tanımlayan daha karmaşık bir örtülü derin bağlantı senaryosu sorgu tabanlı parametreler aşağıda gösterilmiştir:
val baseUri = "http://www.example.com/plants"
fragment<PlantDetailFragment>(nav_routes.plant_detail) {
label = getString(R.string.plant_details_title)
deepLink(navDeepLink {
uriPattern = "${baseUri}/{id}"
})
deepLink(navDeepLink {
uriPattern = "${baseUri}/{id}?name={plant_name}"
})
}
Tekliflerinizi otomatikleştirmek ve optimize etmek için dize interpolasyonu tanımlamayı basitleştirir.
Sınırlamalar
Güvenli Bağımsız Değişkenler eklentisi
Kotlin DSL ile uyumlu değildir. Bunun nedeni, eklentinin
Directions
ve Arguments
sınıflarını oluşturabilirsiniz.
Daha fazla bilgi
Navigasyon türü olarak güvenlik bölümünü inceleyin Kotlin DSL'niz için tür güvenliğini nasıl sağlayacağınızı ve Gezinme Oluşturma Oluşturma kodu.