āύā§āĻāĻŋāĻā§āĻļāύ āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻā§āĻāĻĒā§āϝāĻžāĻ āĻāĻŽā§āĻĒā§āĻ āĻ ā§āϝāĻžāĻĒā§āϞāĻŋāĻā§āĻļāύā§āϰ āĻāύā§āϝ āϏāĻŽāϰā§āĻĨāύ āĻĒā§āϰāĻĻāĻžāύ āĻāϰā§āĨ¤ āύā§āĻāĻŋāĻā§āĻļāύ āĻāĻĒāĻžāĻĻāĻžāύā§āϰ āĻĒāϰāĻŋāĻāĻžāĻ āĻžāĻŽā§ āĻāĻŦāĻ āĻŦā§āĻļāĻŋāώā§āĻā§āϝāĻā§āϞāĻŋāϰ āϏā§āĻŦāĻŋāϧāĻž āĻā§āϰāĻšāĻŖ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻāĻĒāύāĻŋ āĻāĻŽā§āĻĒā§āĻā§āĻŦāϞāĻā§āϞāĻŋāϰ āĻŽāϧā§āϝ⧠āύā§āĻāĻŋāĻā§āĻ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύāĨ¤
āϰāĻāύāĻžāϰ āĻāύā§āϝ āĻŦāĻŋāĻļā§āώāĻāĻžāĻŦā§ āύāĻŋāϰā§āĻŽāĻŋāϤ āϏāϰā§āĻŦāĻļā§āώ āĻāϞāĻĢāĻž āύā§āĻāĻŋāĻā§āĻļāύ āϞāĻžāĻāĻŦā§āϰā§āϰāĻŋāϰ āĻāύā§āϝ, āύā§āĻāĻŋāĻā§āĻļāύ 3 āĻĄāĻā§āĻŽā§āύā§āĻā§āĻļāύ āĻĻā§āĻā§āύāĨ¤
āϏā§āĻāĻāĻĒ
āϰāĻāύāĻž āϏāĻŽāϰā§āĻĨāύ āĻāϰāϤā§, āĻāĻĒāύāĻžāϰ āĻ
ā§āϝāĻžāĻĒ āĻŽāĻĄāĻŋāĻāϞā§āϰ build.gradle
āĻĢāĻžāĻāϞ⧠āύāĻŋāĻŽā§āύāϞāĻŋāĻāĻŋāϤ āύāĻŋāϰā§āĻāϰāϤāĻž āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύ:
āĻā§āϰā§āĻāĻŋ
dependencies { def nav_version = "2.9.3" implementation "androidx.navigation:navigation-compose:$nav_version" }
āĻā§āĻāϞāĻŋāύ
dependencies { val nav_version = "2.9.3" implementation("androidx.navigation:navigation-compose:$nav_version") }
āĻļā§āϰ⧠āĻāϰā§āύ
āĻāĻāĻāĻŋ āĻ ā§āϝāĻžāĻĒā§ āύā§āĻāĻŋāĻā§āĻļāύ āĻĒā§āϰāϝāĻŧā§āĻ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ, āĻāĻāĻāĻŋ āύā§āĻāĻŋāĻā§āĻļāύ āĻšā§āϏā§āĻ, āĻā§āϰāĻžāĻĢ āĻāĻŦāĻ āĻāύā§āĻā§āϰā§āϞāĻžāϰ āĻĒā§āϰāϝāĻŧā§āĻ āĻāϰā§āύāĨ¤ āĻāϰāĻ āϤāĻĨā§āϝā§āϰ āĻāύā§āϝ, āύā§āĻāĻŋāĻā§āĻļāύ āĻāĻāĻžāϰāĻāĻŋāĻ āĻĻā§āĻā§āύāĨ¤
āĻāĻāĻāĻŋ NavController āϤā§āϰāĻŋ āĻāϰā§āύ
āĻāĻŽā§āĻĒā§āĻā§ āĻā§āĻāĻžāĻŦā§ āĻāĻāĻāĻŋ NavController
āϤā§āϰāĻŋ āĻāϰāĻŦā§āύ āϏ⧠āϏāĻŽā§āĻĒāϰā§āĻā§ āϤāĻĨā§āϝā§āϰ āĻāύā§āϝ, āĻāĻāĻāĻŋ āύā§āĻāĻŋāĻā§āĻļāύ āĻāύā§āĻā§āϰā§āϞāĻžāϰ āϤā§āϰāĻŋ āĻāϰā§āύ āĻāϰ āϰāĻāύāĻž āĻŦāĻŋāĻāĻžāĻāĻāĻŋ āĻĻā§āĻā§āύāĨ¤
āĻāĻāĻāĻŋ NavHost āϤā§āϰāĻŋ āĻāϰā§āύ
āĻāĻŽā§āĻĒā§āĻā§ āĻā§āĻāĻžāĻŦā§ āĻāĻāĻāĻŋ NavHost
āϤā§āϰāĻŋ āĻāϰāĻŦā§āύ āϏ⧠āϏāĻŽā§āĻĒāϰā§āĻā§ āϤāĻĨā§āϝā§āϰ āĻāύā§āϝ, āĻāĻĒāύāĻžāϰ āύā§āĻāĻŋāĻā§āĻļāύ āĻā§āϰāĻžāĻĢ āĻĄāĻŋāĻāĻžāĻāύā§āϰ āϰāĻāύāĻž āĻŦāĻŋāĻāĻžāĻāĻāĻŋ āĻĻā§āĻā§āύāĨ¤
āĻāĻāĻāĻŋ āĻāĻŽā§āĻĒā§āĻā§āĻŦāϞ āύā§āĻāĻŋāĻā§āĻ āĻāϰā§āύ
āĻāĻāĻāĻŋ āĻāĻŽā§āĻĒā§āĻā§āĻŦāϞ⧠āύā§āĻāĻŋāĻā§āĻ āĻāϰāĻžāϰ āϤāĻĨā§āϝā§āϰ āĻāύā§āϝ, āĻāϰā§āĻāĻŋāĻā§āĻāĻāĻžāϰ āĻĄāĻā§āĻŽā§āύā§āĻā§āĻļāύ⧠āĻāĻāĻāĻŋ āĻāύā§āϤāĻŦā§āϝ⧠āύā§āĻāĻŋāĻā§āĻ āĻĻā§āĻā§āύāĨ¤
āϝā§āĻā§āϤāĻŋ āĻĻāĻŋāϝāĻŧā§ āύā§āĻāĻŋāĻā§āĻ āĻāϰā§āύ
āĻāĻŽā§āĻĒā§āĻāϝā§āĻā§āϝ āĻāύā§āϤāĻŦā§āϝāĻā§āϞāĻŋāϰ āĻŽāϧā§āϝ⧠āĻāϰā§āĻā§āĻŽā§āύā§āĻ āĻĒāĻžāϏ āĻāϰāĻžāϰ āϤāĻĨā§āϝā§āϰ āĻāύā§āϝ, āĻāĻĒāύāĻžāϰ āύā§āĻāĻŋāĻā§āĻļāύ āĻā§āϰāĻžāĻĢ āĻĄāĻŋāĻāĻžāĻāύ āĻāϰā§āύ āĻāϰ āϰāĻāύāĻž āĻŦāĻŋāĻāĻžāĻāĻāĻŋ āĻĻā§āĻā§āύāĨ¤
āύā§āĻāĻŋāĻā§āĻ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻāĻāĻŋāϞ āĻĄā§āĻāĻž āĻĒā§āύāϰā§āĻĻā§āϧāĻžāϰ āĻāϰā§āύ
āύā§āĻāĻŋāĻā§āĻ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻāĻāĻŋāϞ āĻĄā§āĻāĻž āĻ āĻŦāĻā§āĻā§āĻā§āϰ āĻāĻļā§āĻĒāĻžāĻļā§ āύāĻž āϝāĻžāĻāϝāĻŧāĻžāϰ āĻāύā§āϝ āĻĻā§āĻĸāĻŧāĻāĻžāĻŦā§ āĻĒāϰāĻžāĻŽāϰā§āĻļ āĻĻā§āĻāϝāĻŧāĻž āĻšāϝāĻŧ, āĻŦāϰāĻ āύā§āϝāĻžāĻāĻŋāĻā§āĻļāύ āĻ ā§āϝāĻžāĻāĻļāύāĻā§āϞāĻŋ āϏāĻŽā§āĻĒāĻžāĻĻāύ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻāϰā§āĻā§āĻŽā§āύā§āĻ āĻšāĻŋāϏāĻžāĻŦā§ āύā§āϝā§āύāϤāĻŽ āĻĒā§āϰāϝāĻŧā§āĻāύā§āϝāĻŧ āϤāĻĨā§āϝ, āϝā§āĻŽāύ āĻāĻāĻāĻŋ āĻ āύāύā§āϝ āĻļāύāĻžāĻā§āϤāĻāĻžāϰ⧠āĻŦāĻž āĻ āύā§āϝ āϧāϰāύā§āϰ āĻāĻāĻĄāĻŋ āĻĒāĻžāϏ āĻāϰā§āύ:
// Pass only the user ID when navigating to a new destination as argument
navController.navigate(Profile(id = "user1234"))
āĻāĻāĻŋāϞ āĻŦāϏā§āϤā§āĻā§āϞāĻŋāĻā§ āĻĄā§āĻāĻž āϏā§āϤāϰā§āϰ āĻŽāϤ⧠āϏāϤā§āϝā§āϰ āĻāĻāĻ āĻā§āϏ⧠āĻĄā§āĻāĻž āĻšāĻŋāϏāĻžāĻŦā§ āϏāĻāϰāĻā§āώāĻŖ āĻāϰāĻž āĻāĻāĻŋāϤāĨ¤ āĻāĻāĻŦāĻžāϰ āĻāĻĒāύāĻŋ āύā§āĻāĻŋāĻā§āĻ āĻāϰāĻžāϰ āĻĒāϰ⧠āĻāĻĒāύāĻžāϰ āĻāύā§āϤāĻŦā§āϝ⧠āĻ
āĻŦāϤāϰāĻŖ āĻāϰāϞā§, āĻāĻĒāύāĻŋ āĻĒāĻžāϏ āĻāϰāĻž āĻāĻāĻĄāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āϏāϤā§āϝā§āϰ āĻāĻāĻ āĻā§āϏ āĻĨā§āĻā§ āĻĒā§āϰāϝāĻŧā§āĻāύā§āϝāĻŧ āϤāĻĨā§āϝ āϞā§āĻĄ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύāĨ¤ āĻĄā§āĻāĻž āϏā§āϤāϰ āĻ
ā§āϝāĻžāĻā§āϏā§āϏ āĻāϰāĻžāϰ āĻāύā§āϝ āĻĻāĻžāϝāĻŧā§ āĻāĻĒāύāĻžāϰ ViewModel
āĻāϰ āĻāϰā§āĻā§āĻŽā§āύā§āĻāĻā§āϞāĻŋ āĻĒā§āύāϰā§āĻĻā§āϧāĻžāϰ āĻāϰāϤā§, ViewModel
āĻāϰ SavedStateHandle
āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύ:
class UserViewModel(
savedStateHandle: SavedStateHandle,
private val userInfoRepository: UserInfoRepository
) : ViewModel() {
private val profile = savedStateHandle.toRoute<Profile>()
// Fetch the relevant user information from the data layer,
// ie. userInfoRepository, based on the passed userId argument
private val userInfo: Flow<UserInfo> = userInfoRepository.getUserInfo(profile.id)
// âĻ
}
āĻāĻ āĻĒāĻĻā§āϧāϤāĻŋāĻāĻŋ āĻāύāĻĢāĻŋāĻāĻžāϰā§āĻļāύ āĻĒāϰāĻŋāĻŦāϰā§āϤāύā§āϰ āϏāĻŽāϝāĻŧ āĻĄā§āĻāĻž āĻā§āώāϤāĻŋ āĻĒā§āϰāϤāĻŋāϰā§āϧ āĻāϰāϤ⧠āϏāĻžāĻšāĻžāϝā§āϝ āĻāϰ⧠āĻāĻŦāĻ āϝāĻāύ āĻĒā§āϰāĻļā§āύ⧠āĻĨāĻžāĻāĻž āĻŦāϏā§āϤā§āĻāĻŋ āĻāĻĒāĻĄā§āĻ āĻŦāĻž āĻŽāĻŋāĻāĻā§āĻ āĻāϰāĻž āĻšāϝāĻŧ āϤāĻāύ āĻā§āύ⧠āĻ āϏāĻā§āĻāϤāĻŋāĨ¤
āĻāĻĒāύāĻŋ āĻā§āύ āĻāĻāĻŋāϞ āĻĄā§āĻāĻžāĻā§ āĻāϰā§āĻā§āĻŽā§āύā§āĻ āĻšāĻŋāϏā§āĻŦā§ āĻĒāĻžāϏ āĻāϰāĻž āĻāĻĄāĻŧāĻŋāϝāĻŧā§ āϝāĻžāĻŦā§āύ, āϏā§āĻāϏāĻžāĻĨā§ āϏāĻŽāϰā§āĻĨāĻŋāϤ āĻāϰā§āĻā§āĻŽā§āύā§āĻ āĻĒā§āϰāĻāĻžāϰā§āϰ āϤāĻžāϞāĻŋāĻāĻžāϰ āĻāϰāĻ āĻāĻā§āϰ āĻŦā§āϝāĻžāĻā§āϝāĻžāϰ āĻāύā§āϝ, āĻāύā§āϤāĻŦā§āϝā§āϰ āĻŽāϧā§āϝ⧠āĻĄā§āĻāĻž āĻĒāĻžāϏ āĻāϰā§āύ āĻĻā§āĻā§āύāĨ¤
āĻāĻā§āϰ āϞāĻŋāĻā§āĻ
āύā§āĻāĻŋāĻā§āĻļāύ āĻāĻŽā§āĻĒā§āĻ āĻāĻā§āϰ āϞāĻŋāĻā§āĻāĻā§āϞāĻŋāĻā§ āϏāĻŽāϰā§āĻĨāύ āĻāϰ⧠āϝāĻž composable()
āĻĢāĻžāĻāĻļāύā§āϰ āĻ
āĻāĻļ āĻšāĻŋāϏāĻžāĻŦā§āĻ āϏāĻāĻā§āĻāĻžāϝāĻŧāĻŋāϤ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰā§āĨ¤ āĻāϰ deepLinks
āĻĒā§āϝāĻžāϰāĻžāĻŽāĻŋāĻāĻžāϰāĻāĻŋ NavDeepLink
āĻ
āĻŦāĻā§āĻā§āĻā§āϰ āĻāĻāĻāĻŋ āϤāĻžāϞāĻŋāĻāĻž āĻā§āϰāĻšāĻŖ āĻāϰ⧠āϝāĻž navDeepLink()
āĻĒāĻĻā§āϧāϤāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻĻā§āϰā§āϤ āϤā§āϰāĻŋ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰā§:
@Serializable data class Profile(val id: String)
val uri = "https://www.example.com"
composable<Profile>(
deepLinks = listOf(
navDeepLink<Profile>(basePath = "$uri/profile")
)
) { backStackEntry ->
ProfileScreen(id = backStackEntry.toRoute<Profile>().id)
}
āĻāĻ āĻāĻā§āϰ āϞāĻŋāĻā§āĻāĻā§āϞāĻŋ āĻāĻĒāύāĻžāĻā§ āĻāĻāĻāĻŋ āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ āĻāĻāĻāϰāĻāϞ, āĻ
ā§āϝāĻžāĻāĻļāύ āĻŦāĻž āĻŽāĻžāĻāĻŽ āĻāĻžāĻāĻĒ āĻāĻāĻāĻŋ āĻāĻŽā§āĻĒā§āĻā§āĻŦāϞā§āϰ āϏāĻžāĻĨā§ āϏāĻāϝā§āĻā§āϤ āĻāϰāϤ⧠āĻĻā§āϝāĻŧāĨ¤ āĻĄāĻŋāĻĢāϞā§āĻāϰā§āĻĒā§, āĻāĻ āĻāĻā§āϰ āϞāĻŋāĻā§āĻāĻā§āϞāĻŋ āĻŦāĻžāĻšā§āϝāĻŋāĻ āĻ
ā§āϝāĻžāĻĒāĻā§āϞāĻŋāϰ āĻāĻžāĻā§ āĻĒā§āϰāĻāĻžāĻļ āĻāϰāĻž āĻšāϝāĻŧ āύāĻžā§ˇ āĻāĻ āĻĄāĻŋāĻĒ āϞāĻŋāĻā§āĻāĻā§āϞāĻŋāĻā§ āĻŦāĻžāĻšā§āϝāĻŋāĻāĻāĻžāĻŦā§ āĻāĻĒāϞāĻŦā§āϧ āĻāϰāϤ⧠āĻāĻĒāύāĻžāĻā§ āĻ
āĻŦāĻļā§āϝāĻ āĻāĻĒāύāĻžāϰ āĻ
ā§āϝāĻžāĻĒā§āϰ manifest.xml
āĻĢāĻžāĻāϞ⧠āĻāĻĒāϝā§āĻā§āϤ <intent-filter>
āĻāĻĒāĻžāĻĻāĻžāύ āϝā§āĻ āĻāϰāϤ⧠āĻšāĻŦā§āĨ¤ āĻĒā§āϰā§āĻŦāĻŦāϰā§āϤ⧠āĻāĻĻāĻžāĻšāϰāĻŖā§ āĻāĻā§āϰ āϞāĻŋāĻā§āĻāĻāĻŋ āϏāĻā§āώāĻŽ āĻāϰāϤā§, āĻāĻĒāύāĻžāĻā§ āĻŽā§āϝāĻžāύāĻŋāĻĢā§āϏā§āĻā§āϰ <activity>
āĻāĻĒāĻžāĻĻāĻžāύā§āϰ āĻāĻŋāϤāϰ⧠āύāĻŋāĻŽā§āύāϞāĻŋāĻāĻŋāϤāĻāĻŋ āϝā§āĻā§āϤ āĻāϰāϤ⧠āĻšāĻŦā§:
<activity âĻ>
<intent-filter>
...
<data android:scheme="https" android:host="www.example.com" />
</intent-filter>
</activity>
āύā§āϝāĻžāĻāĻŋāĻā§āĻļāύ āϏā§āĻŦāϝāĻŧāĻāĻā§āϰāĻŋāϝāĻŧāĻāĻžāĻŦā§ āϏā§āĻ āĻāĻŽā§āĻĒā§āĻā§āĻŦāϞ⧠āĻāĻā§āϰ āϞāĻŋāĻā§āĻāĻā§āϞāĻŋāĻā§ āϏāĻāϝā§āĻā§āϤ āĻāϰ⧠āϝāĻāύ āĻāĻā§āϰ āϞāĻŋāĻā§āĻāĻāĻŋ āĻ āύā§āϝ āĻ ā§āϝāĻžāĻĒ āĻĻā§āĻŦāĻžāϰāĻž āĻā§āϰāĻŋāĻāĻžāϰ āĻšāϝāĻŧāĨ¤
āĻāĻ āĻāĻāĻ āĻāĻā§āϰ āϞāĻŋāĻā§āĻāĻā§āϞāĻŋ āĻāĻāĻāĻŋ āĻāĻŽā§āĻĒā§āĻā§āĻŦāϞ āĻĨā§āĻā§ āĻāĻĒāϝā§āĻā§āϤ āĻāĻā§āϰ āϞāĻŋāĻā§āĻ āϏāĻš āĻāĻāĻāĻŋ PendingIntent
āϤā§āϰāĻŋ āĻāϰāϤ⧠āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰā§:
val id = "exampleId"
val context = LocalContext.current
val deepLinkIntent = Intent(
Intent.ACTION_VIEW,
"https://www.example.com/profile/$id".toUri(),
context,
MyActivity::class.java
)
val deepLinkPendingIntent: PendingIntent? = TaskStackBuilder.create(context).run {
addNextIntentWithParentStack(deepLinkIntent)
getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
}
āϤāĻžāϰāĻĒāϰ āĻāĻĒāύāĻŋ āĻĄāĻŋāĻĒ āϞāĻŋāĻā§āĻā§āϰ āĻāύā§āϤāĻŦā§āϝ⧠āĻāĻĒāύāĻžāϰ āĻ
ā§āϝāĻžāĻĒ āĻā§āϞāϤ⧠āĻ
āύā§āϝ āϝā§āĻā§āύ⧠PendingIntent
āĻŽāϤ⧠āĻāĻ deepLinkPendingIntent
āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύāĨ¤
āύā§āϏā§āĻā§āĻĄ āύā§āĻāĻŋāĻā§āĻļāύ
āύā§āϏā§āĻā§āĻĄ āύā§āĻāĻŋāĻā§āĻļāύ āĻā§āϰāĻžāĻĢāĻā§āϞāĻŋ āĻā§āĻāĻžāĻŦā§ āϤā§āϰāĻŋ āĻāϰāĻŦā§āύ āϏ⧠āϏāĻŽā§āĻĒāϰā§āĻā§ āϤāĻĨā§āϝā§āϰ āĻāύā§āϝ, āύā§āϏā§āĻā§āĻĄ āĻā§āϰāĻžāĻĢāĻā§āϞāĻŋ āĻĻā§āĻā§āύāĨ¤
āύāĻŋāĻā§āϰ āĻāύāĻāĻāĻŋ āĻŦāĻžāϰā§āϰ āϏāĻžāĻĨā§ āĻāύā§āĻāĻŋāĻā§āϰā§āĻļāύ
āĻāĻĒāύāĻžāϰ āϏāĻāĻŽāĻŋāĻļā§āϰāĻŖāϝā§āĻā§āϝ āĻ
āύā§āĻā§āϰāĻŽā§āϰ āĻāĻāĻāĻŋ āĻāĻā§āĻ āϏā§āϤāϰ⧠NavController
āϏāĻāĻā§āĻāĻžāϝāĻŧāĻŋāϤ āĻāϰā§, āĻāĻĒāύāĻŋ āĻ
āύā§āϝāĻžāύā§āϝ āĻāĻĒāĻžāĻĻāĻžāύ āϝā§āĻŽāύ āύā§āĻā§āϰ āύā§āĻāĻŋāĻā§āĻļāύ āĻāĻĒāĻžāĻĻāĻžāύāĻā§āϞāĻŋāϰ āϏāĻžāĻĨā§ āύā§āĻāĻŋāĻā§āĻļāύ āϏāĻāϝā§āĻ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύāĨ¤ āĻāĻāĻŋ āĻāϰāĻžāϰ āĻĢāϞ⧠āĻāĻĒāύāĻŋ āύā§āĻā§āϰ āĻŦāĻžāϰ⧠āĻāĻāĻāύāĻā§āϞāĻŋ āύāĻŋāϰā§āĻŦāĻžāĻāύ āĻāϰ⧠āύā§āĻāĻŋāĻā§āĻ āĻāϰāϤ⧠āĻĒāĻžāϰāĻŦā§āύ⧎
BottomNavigation
āĻāĻŦāĻ BottomNavigationItem
āĻāĻĒāĻžāĻĻāĻžāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤā§, āĻāĻĒāύāĻžāϰ Android āĻ
ā§āϝāĻžāĻĒā§āϞāĻŋāĻā§āĻļāύ⧠androidx.compose.material
āύāĻŋāϰā§āĻāϰāϤāĻž āϝā§āĻ āĻāϰā§āύāĨ¤
āĻā§āϰā§āĻāĻŋ
dependencies { implementation "androidx.compose.material:material:1.9.0" } android { buildFeatures { compose true } composeOptions { kotlinCompilerExtensionVersion = "1.5.15" } kotlinOptions { jvmTarget = "1.8" } }
āĻā§āĻāϞāĻŋāύ
dependencies { implementation("androidx.compose.material:material:1.9.0") } android { buildFeatures { compose = true } composeOptions { kotlinCompilerExtensionVersion = "1.5.15" } kotlinOptions { jvmTarget = "1.8" } }
āĻāĻĒāύāĻžāϰ āύā§āĻāĻŋāĻā§āĻļāύ āĻā§āϰāĻžāĻĢā§āϰ āϰā§āĻā§āϰ āϏāĻžāĻĨā§ āύā§āĻā§āϰ āύā§āĻāĻŋāĻā§āĻļāύ āĻŦāĻžāϰ⧠āĻĨāĻžāĻāĻž āĻāĻāĻā§āĻŽāĻā§āϞāĻŋāĻā§ āϞāĻŋāĻā§āĻ āĻāϰāĻžāϰ āĻāύā§āϝ, āĻāĻāĻžāύ⧠āĻĻā§āĻāĻžāύ⧠TopLevelRoute
āĻāϰ āĻŽāϤ⧠āĻāĻāĻāĻŋ āĻā§āϞāĻžāϏ āϏāĻāĻā§āĻāĻžāϝāĻŧāĻŋāϤ āĻāϰāĻžāϰ āĻĒāϰāĻžāĻŽāϰā§āĻļ āĻĻā§āĻāϝāĻŧāĻž āĻšāĻā§āĻā§, āϝāĻžāϰ āĻāĻāĻāĻŋ āϰā§āĻ āĻā§āϞāĻžāϏ āĻāĻŦāĻ āĻāĻāĻāĻŋ āĻāĻāĻāύ āϰāϝāĻŧā§āĻā§ā§ˇ
data class TopLevelRoute<T : Any>(val name: String, val route: T, val icon: ImageVector)
āϤāĻžāϰāĻĒāϰ āϏā§āĻ āϰā§āĻāĻā§āϞāĻŋāĻā§ āĻāĻāĻāĻŋ āϤāĻžāϞāĻŋāĻāĻžāϝāĻŧ āϰāĻžāĻā§āύ āϝāĻž BottomNavigationItem
āĻĻā§āĻŦāĻžāϰāĻž āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰā§:
val topLevelRoutes = listOf(
TopLevelRoute("Profile", Profile, Icons.Profile),
TopLevelRoute("Friends", Friends, Icons.Friends)
)
āĻāĻĒāύāĻžāϰ BottomNavigation
composable āĻ, currentBackStackEntryAsState()
āĻĢāĻžāĻāĻļāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻŦāϰā§āϤāĻŽāĻžāύ NavBackStackEntry
āĻĒāĻžāύāĨ¤ āĻāĻ āĻāύā§āĻā§āϰāĻŋ āĻāĻĒāύāĻžāĻā§ āĻŦāϰā§āϤāĻŽāĻžāύ NavDestination
āĻ āĻ
ā§āϝāĻžāĻā§āϏā§āϏ āĻĻā§āϝāĻŧāĨ¤ āĻĒā§āϰāϤāĻŋāĻāĻŋ BottomNavigationItem
āĻāϰ āύāĻŋāϰā§āĻŦāĻžāĻāĻŋāϤ āĻ
āĻŦāϏā§āĻĨāĻž āϤāĻžāϰāĻĒāϰ⧠āĻŦāϰā§āϤāĻŽāĻžāύ āĻāύā§āϤāĻŦā§āϝā§āϰ āϰā§āĻā§āϰ āϏāĻžāĻĨā§ āĻāĻāĻā§āĻŽā§āϰ āϰā§āĻ āĻāĻŦāĻ āĻāϰ āĻŽā§āϞ āĻāύā§āϤāĻŦā§āϝāĻā§āϞāĻŋāϰ āϏāĻžāĻĨā§ āϤā§āϞāύāĻž āĻāϰ⧠āύāĻŋāϰā§āϧāĻžāϰāĻŖ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰ⧠āϝāĻāύ āĻāĻĒāύāĻŋ NavDestination
āĻļā§āϰā§āĻŖā§āĻŦāĻŋāύā§āϝāĻžāϏ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āύā§āϏā§āĻā§āĻĄ āύā§āĻāĻŋāĻā§āĻļāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻā§āύāĨ¤
navigate
āĻāύā§āϝ āĻāĻāĻāĻŋ āĻāϞā§āϰ āϏāĻžāĻĨā§ onClick
lambda āϏāĻāϝā§āĻ āĻāϰāϤ⧠āĻāĻāĻā§āĻŽā§āϰ āϰā§āĻāĻāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āĻšāϝāĻŧ āϝāĻžāϤ⧠āĻāĻāĻā§āĻŽāĻāĻŋāϤ⧠āĻā§āϝāĻžāĻĒ āĻāϰāĻž āϏā§āĻ āĻāĻāĻā§āĻŽā§ āύā§āĻāĻŋāĻā§āĻ āĻāϰā§āĨ¤ saveState
āĻāĻŦāĻ restoreState
āĻĒāϤāĻžāĻāĻž āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§, āĻāĻĒāύāĻŋ āύā§āĻā§āϰ āύā§āĻāĻŋāĻā§āĻļāύ āĻāĻāĻā§āĻŽāĻā§āϞāĻŋāϰ āĻŽāϧā§āϝ⧠āĻ
āĻĻāϞāĻŦāĻĻāϞ āĻāϰāĻžāϰ āϏāĻžāĻĨā§ āϏāĻžāĻĨā§ āϏā§āĻ āĻāĻāĻā§āĻŽā§āϰ āϰāĻžāĻā§āϝ āĻāĻŦāĻ āĻĒāĻŋāĻāύā§āϰ āϏā§āĻā§āϝāĻžāĻ āϏāĻ āĻŋāĻāĻāĻžāĻŦā§ āϏāĻāϰāĻā§āώāĻŋāϤ āĻāĻŦāĻ āĻĒā§āύāϰā§āĻĻā§āϧāĻžāϰ āĻāϰāĻž āĻšāϝāĻŧāĨ¤
val navController = rememberNavController()
Scaffold(
bottomBar = {
BottomNavigation {
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
topLevelRoutes.forEach { topLevelRoute ->
BottomNavigationItem(
icon = { Icon(topLevelRoute.icon, contentDescription = topLevelRoute.name) },
label = { Text(topLevelRoute.name) },
selected = currentDestination?.hierarchy?.any { it.hasRoute(topLevelRoute.route::class) } == true,
onClick = {
navController.navigate(topLevelRoute.route) {
// Pop up to the start destination of the graph to
// avoid building up a large stack of destinations
// on the back stack as users select items
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
// Avoid multiple copies of the same destination when
// reselecting the same item
launchSingleTop = true
// Restore state when reselecting a previously selected item
restoreState = true
}
}
)
}
}
}
) { innerPadding ->
NavHost(navController, startDestination = Profile, Modifier.padding(innerPadding)) {
composable<Profile> { ProfileScreen(...) }
composable<Friends> { FriendsScreen(...) }
}
}
āĻāĻāĻžāύ⧠āĻāĻĒāύāĻŋ NavController.currentBackStackEntryAsState()
āĻĒāĻĻā§āϧāϤāĻŋāϰ āϏā§āĻŦāĻŋāϧāĻž āύā§āĻŦā§āύ āϝāĻžāϤ⧠NavHost
āĻĢāĻžāĻāĻļāύ āĻĨā§āĻā§ navController
āϏā§āĻā§āĻāĻāĻŋ āĻāϤā§āϤā§āϞāύ āĻāϰāĻž āϝāĻžāϝāĻŧ āĻāĻŦāĻ āĻāĻāĻŋ BottomNavigation
āĻāĻŽā§āĻĒā§āύā§āύā§āĻā§āϰ āϏāĻžāĻĨā§ āĻļā§āϝāĻŧāĻžāϰ āĻāϰāĻž āϝāĻžāϝāĻŧāĨ¤ āĻāϰ āĻŽāĻžāύ⧠āĻšāϞ BottomNavigation
āϏā§āĻŦāϝāĻŧāĻāĻā§āϰāĻŋāϝāĻŧāĻāĻžāĻŦā§ āϏāĻŦāĻā§āϝāĻŧā§ āĻāĻĒ-āĻā§-āĻĄā§āĻ āĻ
āĻŦāϏā§āĻĨāĻžāĨ¤
āĻāύā§āĻāĻžāϰāĻ āĻĒāĻžāϰā§āĻŦāĻŋāϞāĻŋāĻāĻŋ
āĻāĻĒāύāĻŋ āϝāĻĻāĻŋ āϰāĻāύāĻžāϰ āϏāĻžāĻĨā§ āύā§āĻāĻŋāĻā§āĻļāύ āĻāĻĒāĻžāĻĻāĻžāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻāĻžāύ āϤāĻŦā§ āĻāĻĒāύāĻžāϰ āĻāĻžāĻā§ āĻĻā§āĻāĻŋ āĻŦāĻŋāĻāϞā§āĻĒ āϰāϝāĻŧā§āĻā§:
- āĻāĻŖā§āĻĄā§āϰ āĻāύā§āϝ āύā§āĻāĻŋāĻā§āĻļāύ āĻāĻĒāĻžāĻĻāĻžāύ āϏāĻš āĻāĻāĻāĻŋ āύā§āĻāĻŋāĻā§āĻļāύ āĻā§āϰāĻžāĻĢ āϏāĻāĻā§āĻāĻžāϝāĻŧāĻŋāϤ āĻāϰā§āύāĨ¤
- āĻāĻŽā§āĻĒā§āĻ āĻāύā§āϤāĻŦā§āϝāĻā§āϞāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āϰāĻāύāĻžāϤ⧠āĻāĻāĻāĻŋ
NavHost
āϏāĻš āĻāĻāĻāĻŋ āύā§āĻāĻŋāĻā§āĻļāύ āĻā§āϰāĻžāĻĢ āϏāĻāĻā§āĻāĻžāϝāĻŧāĻŋāϤ āĻāϰā§āύāĨ¤ āύā§āϝāĻžāĻāĻŋāĻā§āĻļāύ āĻā§āϰāĻžāĻĢā§āϰ āϏāĻŽāϏā§āϤ āϏā§āĻā§āϰāĻŋāύ āĻāĻŽā§āĻĒā§āĻā§āĻŦāϞ āĻšāϞā§āĻ āĻāĻāĻŋ āϏāĻŽā§āĻāĻŦāĨ¤
āĻ āϤāĻāĻŦ, āĻŽāĻŋāĻļā§āϰ āϰāĻāύāĻž āĻāĻŦāĻ āĻāĻŋāĻ āĻ ā§āϝāĻžāĻĒāĻā§āϞāĻŋāϰ āĻāύā§āϝ āϏā§āĻĒāĻžāϰāĻŋāĻļ āĻšāϞ āĻĢā§āϰā§āϝāĻžāĻāĻŽā§āύā§āĻ-āĻāĻŋāϤā§āϤāĻŋāĻ āύā§āĻāĻŋāĻā§āĻļāύ āĻāĻĒāĻžāĻĻāĻžāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻžāĨ¤ āĻĢā§āϰā§āϝāĻžāĻāĻŽā§āύā§āĻāĻā§āϞāĻŋ āϤāĻāύ āĻāĻŋāĻ-āĻāĻŋāϤā§āϤāĻŋāĻ āϏā§āĻā§āϰā§āύ, āĻāĻŽā§āĻĒā§āĻ āϏā§āĻā§āϰā§āύ āĻāĻŦāĻ āϏā§āĻā§āϰā§āύāĻā§āϞāĻŋāĻā§ āϧāϰ⧠āϰāĻžāĻāĻŦā§ āϝāĻž āĻāĻŋāĻ āĻāĻŦāĻ āĻāĻŽā§āĻĒā§āĻ āĻāĻāϝāĻŧāĻ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āĨ¤ āĻāĻāĻŦāĻžāϰ āĻĒā§āϰāϤāĻŋāĻāĻŋ āĻĢā§āϰā§āϝāĻžāĻāĻŽā§āύā§āĻā§āϰ āĻŦāĻŋāώāϝāĻŧāĻŦāϏā§āϤ⧠āĻāĻŽā§āĻĒā§āĻā§ āĻšāϝāĻŧā§ āĻā§āϞā§, āĻĒāϰāĻŦāϰā§āϤ⧠āϧāĻžāĻĒ āĻšāϞ āϏā§āĻ āϏāĻŽāϏā§āϤ āϏā§āĻā§āϰā§āύāĻā§āϞāĻŋāĻā§ āύā§āĻāĻŋāĻā§āĻļāύ āĻāĻŽā§āĻĒā§āĻā§āϰ āϏāĻžāĻĨā§ āĻŦā§āĻāϧ⧠āĻĻā§āĻāϝāĻŧāĻž āĻāĻŦāĻ āϏāĻŽāϏā§āϤ āĻā§āĻāϰā§āĻā§āϞāĻŋ āϏāϰāĻŋāϝāĻŧā§ āĻĢā§āϞāĻžāĨ¤
āĻā§āĻāϰāĻžāĻā§āϞāĻŋāϰ āĻāύā§āϝ āύā§āĻāĻŋāĻā§āĻļāύ āϏāĻš āϰāĻāύāĻž āĻĨā§āĻā§ āύā§āĻāĻŋāĻā§āĻ āĻāϰā§āύ
āĻāĻŽā§āĻĒā§āĻ āĻā§āĻĄā§āϰ āĻŽāϧā§āϝ⧠āĻāύā§āϤāĻŦā§āϝ āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻāϰāĻžāϰ āĻāύā§āϝ, āĻāĻĒāύāĻŋ āĻāĻŽāύ āĻāĻā§āύā§āĻāĻā§āϞāĻŋ āĻĒā§āϰāĻāĻžāĻļ āĻāϰā§āύ āϝāĻž āĻ āύā§āĻā§āϰāĻŽā§āϰ āϝā§āĻā§āύ āĻāĻŽā§āĻĒā§āĻā§āĻŦāϞ āĻĻā§āĻŦāĻžāϰāĻž āĻĒāĻžāϏ āĻāϰāĻž āϝāĻžāϝāĻŧ āĻāĻŦāĻ āĻā§āϰāĻŋāĻāĻžāϰ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰā§:
@Composable
fun MyScreen(onNavigate: (Int) -> Unit) {
Button(onClick = { onNavigate(R.id.nav_profile) } { /* ... */ }
}
āĻāĻĒāύāĻžāϰ āĻāĻŖā§āĻĄā§, āĻāĻĒāύāĻŋ NavController
āĻā§āĻāĻā§ āĻāĻŦāĻ āĻāύā§āϤāĻŦā§āϝ⧠āύā§āĻāĻŋāĻā§āĻ āĻāϰāĻžāϰ āĻŽāĻžāϧā§āϝāĻŽā§ āϰāĻāύāĻž āĻāĻŦāĻ āĻāĻŖā§āĻĄ-āĻāĻŋāϤā§āϤāĻŋāĻ āύā§āĻāĻŋāĻā§āĻļāύ āĻāĻĒāĻžāĻĻāĻžāύā§āϰ āĻŽāϧā§āϝ⧠āϏā§āϤ⧠āϤā§āϰāĻŋ āĻāϰā§āύ:
override fun onCreateView( /* ... */ ) {
setContent {
MyScreen(onNavigate = { dest -> findNavController().navigate(dest) })
}
}
āĻŦāĻŋāĻāϞā§āĻĒāĻāĻžāĻŦā§, āĻāĻĒāύāĻŋ āĻāĻĒāύāĻžāϰ āϰāĻāύāĻž āĻ
āύā§āĻā§āϰāĻŽā§āϰ āύāĻŋāĻā§ NavController
āĻĒāĻžāϏ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύāĨ¤ āϝāĻžāĻāĻšā§āĻ, āϏāĻžāϧāĻžāϰāĻŖ āĻĢāĻžāĻāĻļāύ āĻĒā§āϰāĻāĻžāĻļ āĻāϰāĻž āĻ
āύā§āĻ āĻŦā§āĻļāĻŋ āĻĒā§āύāϰāĻžāϝāĻŧ āĻŦā§āϝāĻŦāĻšāĻžāϰāϝā§āĻā§āϝ āĻāĻŦāĻ āĻĒāϰā§āĻā§āώāĻžāϝā§āĻā§āϝāĨ¤
āĻā§āϏā§āĻāĻŋāĻ
āĻāĻĒāύāĻžāϰ āϏāĻāĻŽāĻŋāĻļā§āϰāĻŖāϝā§āĻā§āϝ āĻāύā§āϤāĻŦā§āϝāĻā§āϞāĻŋ āĻĨā§āĻā§ āύā§āĻāĻŋāĻā§āĻļāύ āĻā§āĻĄāĻāĻŋ āĻĻā§āĻŦāĻŋāĻā§āĻŖ āĻāϰā§āύ āϝāĻžāϤ⧠āĻĒā§āϰāϤāĻŋāĻāĻŋ āĻāĻŽā§āĻĒā§āĻā§āĻŦāϞāĻā§ āĻŦāĻŋāĻā§āĻāĻŋāύā§āύāĻāĻžāĻŦā§ āĻĒāϰā§āĻā§āώāĻž āĻāϰāĻž āϝāĻžāϝāĻŧ, āϝāĻž NavHost
āĻāĻŽā§āĻĒā§āĻā§āĻŦāϞ āĻĨā§āĻā§ āĻāϞāĻžāĻĻāĻžāĨ¤
āĻāϰ āĻŽāĻžāύ⧠āĻšāϞ āϝ⧠āĻāĻĒāύāĻžāϰ navController
āĻāϞāĻŦā§āϝāĻžāĻāĻā§āϞāĻŋāĻā§ āĻĒāϰāĻžāĻŽāĻŋāϤāĻŋ āĻšāĻŋāϏāĻžāĻŦā§ āϏāϰāĻžāϏāϰāĻŋ āĻā§āύāĻ āĻāĻŽā§āĻĒā§āĻā§āĻŦāϞ⧠āĻĒāĻžāϏ āĻāϰāĻž āĻāĻāĻŋāϤ āύāϝāĻŧāĨ¤ āĻāĻāĻŋ āĻāĻĒāύāĻžāϰ āϏāĻŽāϏā§āϤ āĻāĻŽā§āĻĒā§āĻā§āĻŦāϞāĻā§ āĻĒā§āĻĨāĻāĻāĻžāĻŦā§ āĻĒāϰā§āĻā§āώāĻžāϝā§āĻā§āϝ āĻšāϤ⧠āĻĻā§āϝāĻŧ, āĻāĻžāϰāĻŖ āϤāĻžāĻĻā§āϰ āĻĒāϰā§āĻā§āώāĻžāϝāĻŧ navController
āĻāĻāĻāĻŋ āĻāĻĻāĻžāĻšāϰāĻŖ āĻĒā§āϰāϝāĻŧā§āĻāύ āĻšāϝāĻŧ āύāĻžāĨ¤
composable
āϞā§āϝāĻžāĻŽā§āĻŦāĻĄāĻž āĻĻā§āĻŦāĻžāϰāĻž āĻĒā§āϰāĻĻāϤā§āϤ āĻĒāϰā§āĻā§āώ āϏā§āϤāϰ āϝāĻž āĻāĻĒāύāĻžāĻā§ āĻāĻĒāύāĻžāϰ āύā§āĻāĻŋāĻā§āĻļāύ āĻā§āĻĄāĻā§ āĻāĻŽā§āĻĒā§āĻā§āĻŦāϞ āĻĨā§āĻā§ āĻāϞāĻžāĻĻāĻž āĻāϰāϤ⧠āĻĻā§āϝāĻŧāĨ¤ āĻāĻāĻŋ āĻĻā§āĻāĻŋ āĻĻāĻŋāĻā§ āĻāĻžāĻ āĻāϰā§:
- āĻāĻĒāύāĻžāϰ āϰāĻāύāĻžāϝā§āĻā§āϝ āĻŽāϧā§āϝ⧠āĻļā§āϧā§āĻŽāĻžāϤā§āϰ āĻĒāĻžāϰā§āϏ āĻāϰā§āĻā§āĻŽā§āύā§āĻ āĻĒāĻžāϏ
- āĻĒāĻžāϏ āϞā§āϝāĻžāĻŽā§āĻŦāĻĄāĻžāϏ āϝāĻž āύā§āĻāĻŋāĻā§āĻ āĻāϰāĻžāϰ āĻāύā§āϝ āĻāĻŽā§āĻĒā§āĻā§āĻŦāϞ āĻĻā§āĻŦāĻžāϰāĻž āĻā§āϰāĻŋāĻāĻžāϰ āĻāϰāĻž āĻāĻāĻŋāϤ, āĻŦāϰāĻ
NavController
āύāĻŋāĻā§āĻāĨ¤
āĻāĻĻāĻžāĻšāϰāĻŖāϏā§āĻŦāϰā§āĻĒ, āĻāĻāĻāĻŋ ProfileScreen
āĻāĻŽā§āĻĒā§āĻāϝā§āĻā§āϝ āϝāĻž āĻāĻāĻāĻŋ userId
āĻāύāĻĒā§āĻ āĻšāĻŋāϏāĻžāĻŦā§ āύā§āϝāĻŧ āĻāĻŦāĻ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āĻĻā§āϰ āĻŦāύā§āϧā§āϰ āĻĒā§āϰā§āĻĢāĻžāĻāϞ āĻĒā§āώā§āĻ āĻžāϝāĻŧ āύā§āĻāĻŋāĻā§āĻ āĻāϰāĻžāϰ āĻ
āύā§āĻŽāϤāĻŋ āĻĻā§āϝāĻŧ āĻāϰ āϏā§āĻŦāĻžāĻā§āώāϰ āĻĨāĻžāĻāϤ⧠āĻĒāĻžāϰā§:
@Composable
fun ProfileScreen(
userId: String,
navigateToFriendProfile: (friendUserId: String) -> Unit
) {
âĻ
}
āĻāĻāĻāĻžāĻŦā§, ProfileScreen
āĻāĻŽā§āĻĒā§āĻā§āĻŦāϞ āύā§āĻāĻŋāĻā§āĻļāύ āĻĨā§āĻā§ āϏā§āĻŦāĻžāϧā§āύāĻāĻžāĻŦā§ āĻāĻžāĻ āĻāϰā§, āĻāĻāĻŋ āϏā§āĻŦāĻžāϧā§āύāĻāĻžāĻŦā§ āĻĒāϰā§āĻā§āώāĻž āĻāϰāĻžāϰ āĻ
āύā§āĻŽāϤāĻŋ āĻĻā§āϝāĻŧāĨ¤ composable
āϞā§āϝāĻžāĻŽā§āĻŦāĻĄāĻž āύā§āĻāĻŋāĻā§āĻļāύ āĻāĻĒāĻŋāĻāĻ āĻāĻŦāĻ āĻāĻĒāύāĻžāϰ āĻāĻŽā§āĻĒā§āĻā§āĻŦāϞā§āϰ āĻŽāϧā§āϝ⧠āĻŦā§āϝāĻŦāϧāĻžāύ āĻĒā§āϰāĻŖ āĻāϰāĻžāϰ āĻāύā§āϝ āĻĒā§āϰāϝāĻŧā§āĻāύā§āϝāĻŧ āύā§āϝā§āύāϤāĻŽ āϞāĻāĻŋāĻāĻā§ āĻāύāĻā§āϝāĻžāĻĒāϏā§āϞā§āĻ āĻāϰāĻŦā§:
@Serializable data class Profile(id: String)
composable<Profile> { backStackEntry ->
val profile = backStackEntry.toRoute<Profile>()
ProfileScreen(userId = profile.id) { friendUserId ->
navController.navigate(route = Profile(id = friendUserId))
}
}
NavHost
āĻĒāϰā§āĻā§āώāĻž āĻāϰ⧠āĻāĻĒāύāĻžāϰ āĻ
ā§āϝāĻžāĻĒ āύā§āĻāĻŋāĻā§āĻļāύ āĻĒā§āϰāϝāĻŧā§āĻāύā§āϝāĻŧāϤāĻžāĻā§āϞāĻŋ āĻāĻāĻžāϰ āĻāϰ⧠āĻāĻŽāύ āĻĒāϰā§āĻā§āώāĻžāĻā§āϞāĻŋ āϞāĻŋāĻāϤ⧠āϏā§āĻĒāĻžāϰāĻŋāĻļ āĻāϰāĻž āĻšāϝāĻŧ, āĻāĻĒāύāĻžāϰ āĻāĻŽā§āĻĒā§āĻā§āĻŦāϞ āĻāĻŦāĻ āĻāĻĒāύāĻžāϰ āĻĒā§āĻĨāĻ āϏā§āĻā§āϰā§āύ āĻāĻŽā§āĻĒā§āĻā§āĻŦāϞāĻā§āϞāĻŋāϤ⧠āĻĒāĻžāϏ āĻāϰāĻž āύā§āĻāĻŋāĻā§āĻļāύ āĻ
ā§āϝāĻžāĻāĻļāύāĻā§āϞāĻŋāĨ¤
NavHost
āĻĒāϰā§āĻā§āώāĻž āĻāϰāĻž āĻšāĻā§āĻā§
āĻāĻĒāύāĻžāϰ NavHost
āĻĒāϰā§āĻā§āώāĻž āĻļā§āϰ⧠āĻāϰāϤā§, āύāĻŋāĻŽā§āύāϞāĻŋāĻāĻŋāϤ āύā§āĻāĻŋāĻā§āĻļāύ-āĻĒāϰā§āĻā§āώāĻž āύāĻŋāϰā§āĻāϰāϤāĻž āϝā§āĻ āĻāϰā§āύ:
dependencies {
// ...
androidTestImplementation "androidx.navigation:navigation-testing:$navigationVersion"
// ...
}
āĻāĻĒāύāĻžāϰ āĻ
ā§āϝāĻžāĻĒā§āϰ NavHost
āĻāĻāĻāĻŋ āĻāĻŽā§āĻĒā§āĻā§āĻŦāϞ⧠āĻŽā§āĻĄāĻŧāĻžāύ⧠āϝāĻž āĻāĻāĻāĻŋ NavHostController
āĻĒā§āϝāĻžāϰāĻžāĻŽāĻŋāĻāĻžāϰ āĻšāĻŋāϏā§āĻŦā§ āĻā§āϰāĻšāĻŖ āĻāϰā§āĨ¤
@Composable
fun AppNavHost(navController: NavHostController){
NavHost(navController = navController){ ... }
}
āύā§āϝāĻžāĻāĻŋāĻā§āĻļāύ āĻā§āϏā§āĻāĻŋāĻ āĻāϰā§āĻāĻŋāĻĢā§āϝāĻžāĻā§āĻ TestNavHostController
āĻāϰ āĻāĻāĻāĻŋ āĻāĻĻāĻžāĻšāϰāĻŖ āĻĒāĻžāϏ āĻāϰ⧠āĻāĻāύ āĻāĻĒāύāĻŋ AppNavHost
āĻāĻŦāĻ NavHost
āĻāĻŋāϤāϰ⧠āϏāĻāĻā§āĻāĻžāϝāĻŧāĻŋāϤ āϏāĻŽāϏā§āϤ āύā§āĻāĻŋāĻā§āĻļāύ āϞāĻāĻŋāĻ āĻĒāϰā§āĻā§āώāĻž āĻāϰāϤ⧠āĻĒāĻžāϰā§āύāĨ¤ āĻāĻāĻāĻŋ UI āĻĒāϰā§āĻā§āώāĻž āϝāĻž āĻāĻĒāύāĻžāϰ āĻ
ā§āϝāĻžāĻĒā§āϰ āĻļā§āϰā§āϰ āĻāύā§āϤāĻŦā§āϝ āϝāĻžāĻāĻžāĻ āĻāϰ⧠āĻāĻŦāĻ NavHost
āĻĻā§āĻāϤ⧠āĻāĻāϰāĻāĻŽ āĻšāĻŦā§:
class NavigationTest {
@get:Rule
val composeTestRule = createComposeRule()
lateinit var navController: TestNavHostController
@Before
fun setupAppNavHost() {
composeTestRule.setContent {
navController = TestNavHostController(LocalContext.current)
navController.navigatorProvider.addNavigator(ComposeNavigator())
AppNavHost(navController = navController)
}
}
// Unit test
@Test
fun appNavHost_verifyStartDestination() {
composeTestRule
.onNodeWithContentDescription("Start Screen")
.assertIsDisplayed()
}
}
āύā§āϝāĻžāĻāĻŋāĻā§āĻļāύ āĻā§āϰāĻŋāϝāĻŧāĻž āĻĒāϰā§āĻā§āώāĻž āĻāϰāĻž āĻšāĻā§āĻā§
āĻāĻĒāύāĻŋ āĻāĻāĻžāϧāĻŋāĻ āĻāĻĒāĻžāϝāĻŧā§ āĻāĻĒāύāĻžāϰ āύā§āĻāĻŋāĻā§āĻļāύ āĻŦāĻžāϏā§āϤāĻŦāĻžāϝāĻŧāύ āĻĒāϰā§āĻā§āώāĻž āĻāϰāϤ⧠āĻĒāĻžāϰā§āύ, UI āĻāĻĒāĻžāĻĻāĻžāύāĻā§āϞāĻŋāϤ⧠āĻā§āϞāĻŋāĻ āĻāϰ⧠āĻāĻŦāĻ āϤāĻžāϰāĻĒāϰ⧠āĻĒā§āϰāĻĻāϰā§āĻļāĻŋāϤ āĻāύā§āϤāĻŦā§āϝ āϝāĻžāĻāĻžāĻ āĻāϰ⧠āĻŦāĻž āĻŦāϰā§āϤāĻŽāĻžāύ āϰā§āĻā§āϰ āϏāĻžāĻĨā§ āĻĒā§āϰāϤā§āϝāĻžāĻļāĻŋāϤ āϰā§āĻā§āϰ āϤā§āϞāύāĻž āĻāϰā§āĨ¤
āϝā§āĻšā§āϤ⧠āĻāĻĒāύāĻŋ āĻāĻĒāύāĻžāϰ āĻāĻāĻā§āϰāĻŋāĻ āĻ ā§āϝāĻžāĻĒā§āϰ āĻŦāĻžāϏā§āϤāĻŦāĻžāϝāĻŧāύ āĻĒāϰā§āĻā§āώāĻž āĻāϰāϤ⧠āĻāĻžāύ, āϤāĻžāĻ UI-āϤ⧠āĻā§āϞāĻŋāĻ āĻāϰāĻž āĻŦāĻžāĻā§āĻāύā§āϝāĻŧāĨ¤ āĻŦāĻŋāĻā§āĻāĻŋāύā§āύāĻāĻžāĻŦā§ āĻĒā§āĻĨāĻ āϏāĻāĻŽāĻŋāĻļā§āϰāĻŖāϝā§āĻā§āϝ āĻĢāĻžāĻāĻļāύāĻā§āϞāĻŋāϰ āĻĒāĻžāĻļāĻžāĻĒāĻžāĻļāĻŋ āĻāĻāĻŋ āĻā§āĻāĻžāĻŦā§ āĻĒāϰā§āĻā§āώāĻž āĻāϰāĻž āϝāĻžāϝāĻŧ āϤāĻž āĻļāĻŋāĻāϤā§, āĻā§āĻāĻĒā§āϝāĻžāĻ āĻāĻŽā§āĻĒā§āĻ āĻā§āĻĄāϞā§āϝāĻžāĻŦā§ āĻĒāϰā§āĻā§āώāĻžāĻāĻŋ āĻĒāϰā§āĻā§āώāĻž āĻāϰ⧠āĻĻā§āĻā§āύāĨ¤
āĻāĻāĻžāĻĄāĻŧāĻžāĻ āĻāĻĒāύāĻŋ navController
āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻŦāϰā§āϤāĻŽāĻžāύ āϰā§āĻāĻāĻŋāĻā§ āĻĒā§āϰāϤā§āϝāĻžāĻļāĻŋāϤ āϰā§āĻā§āϰ āϏāĻžāĻĨā§ āϤā§āϞāύāĻž āĻāϰā§, navController
āĻāϰ currentBackStackEntry
āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻāĻĒāύāĻžāϰ āĻĻāĻžāĻŦāĻŋāĻā§āϞāĻŋ āĻĒāϰā§āĻā§āώāĻž āĻāϰāϤ⧠āĻĒāĻžāϰā§āύ:
@Test
fun appNavHost_clickAllProfiles_navigateToProfiles() {
composeTestRule.onNodeWithContentDescription("All Profiles")
.performScrollTo()
.performClick()
assertTrue(navController.currentBackStackEntry?.destination?.hasRoute<Profile>() ?: false)
}
āĻāĻŽā§āĻĒā§āĻ āĻā§āϏā§āĻāĻŋāĻ āĻŦā§āϏāĻŋāĻ āϏāĻŽā§āĻĒāϰā§āĻā§ āĻāϰāĻ āύāĻŋāϰā§āĻĻā§āĻļāύāĻžāϰ āĻāύā§āϝ, āĻāĻĒāύāĻžāϰ āĻāĻŽā§āĻĒā§āĻ āϞā§āĻāĻāĻ āĻĒāϰā§āĻā§āώāĻž āĻāϰāĻž āĻāĻŦāĻ āĻā§āĻāĻĒā§āϝāĻžāĻ āĻāĻŽā§āĻĒā§āĻ āĻā§āĻĄāϞā§āϝāĻžāĻŦā§ āĻā§āϏā§āĻāĻŋāĻ āĻĻā§āĻā§āύāĨ¤ āύā§āĻāĻŋāĻā§āĻļāύ āĻā§āĻĄā§āϰ āĻāύā§āύāϤ āĻĒāϰā§āĻā§āώāĻžāϰ āĻŦāĻŋāώāϝāĻŧā§ āĻāϰāĻ āĻāĻžāύāϤā§, āĻā§āϏā§āĻ āύā§āĻāĻŋāĻā§āĻļāύ āĻāĻžāĻāĻĄ āĻĻā§āĻā§āύāĨ¤
āĻāϰāĻ āĻāĻžāύā§āύ
āĻā§āĻāĻĒā§āϝāĻžāĻ āύā§āĻāĻŋāĻā§āĻļāύ āϏāĻŽā§āĻĒāϰā§āĻā§ āĻāϰāĻ āĻāĻžāύāϤā§, āύā§āĻāĻŋāĻā§āĻļāύ āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻĻāĻŋāϝāĻŧā§ āĻļā§āϰ⧠āĻāϰā§āύ āĻĻā§āĻā§āύ āĻŦāĻž āĻā§āĻāĻĒā§āϝāĻžāĻ āĻāĻŽā§āĻĒā§āĻ āύā§āĻāĻŋāĻā§āĻļāύ āĻā§āĻĄāϞā§āϝāĻžāĻŦ āύāĻŋāύāĨ¤
āĻāĻĒāύāĻžāϰ āĻ ā§āϝāĻžāĻĒā§āϰ āύā§āĻāĻŋāĻā§āĻļāύ āĻā§āĻāĻžāĻŦā§ āĻĄāĻŋāĻāĻžāĻāύ āĻāϰāĻŦā§āύ āϤāĻž āĻļāĻŋāĻāϤ⧠āϝāĻžāϤ⧠āĻāĻāĻŋ āĻŦāĻŋāĻāĻŋāύā§āύ āϏā§āĻā§āϰā§āύā§āϰ āĻāĻāĻžāϰ, āĻ āĻāĻŋāϝā§āĻāύ āĻāĻŦāĻ āĻĢāϰā§āĻŽ āĻĢā§āϝāĻžāĻā§āĻāϰāĻā§āϞāĻŋāϰ āϏāĻžāĻĨā§ āĻāĻžāĻĒ āĻāĻžāϝāĻŧ, āĻĒā§āϰāϤāĻŋāĻā§āϰāĻŋāϝāĻŧāĻžāĻļā§āϞ UI āĻāϰ āĻāύā§āϝ āύā§āĻāĻŋāĻā§āĻļāύ āĻĻā§āĻā§āύāĨ¤
āύā§āϏā§āĻā§āĻĄ āĻā§āϰāĻžāĻĢ āĻāĻŦāĻ āύāĻŋāĻā§āϰ āύā§āĻāĻŋāĻā§āĻļāύ āĻŦāĻžāϰ āĻāύā§āĻāĻŋāĻā§āϰā§āĻļāύā§āϰ āĻŽāϤ āϧāĻžāϰāĻŖāĻž āϏāĻš āĻāĻāĻāĻŋ āĻŽāĻĄā§āϞāĻžāϰāĻžāĻāĻāĻĄ āĻ ā§āϝāĻžāĻĒā§ āĻāϰāĻ āĻāύā§āύāϤ āĻāĻŽā§āĻĒā§āĻ āύā§āĻāĻŋāĻā§āĻļāύ āĻŦāĻžāϏā§āϤāĻŦāĻžāϝāĻŧāύ āϏāĻŽā§āĻĒāϰā§āĻā§ āĻāĻžāύāϤā§, GitHub-āĻ Now in Android āĻ ā§āϝāĻžāĻĒāĻāĻŋ āĻĻā§āĻā§āύāĨ¤
āύāĻŽā§āύāĻž
āĻāĻĒāύāĻžāϰ āĻāύā§āϝ āĻĒā§āϰāϏā§āϤāĻžāĻŦāĻŋāϤ
- āĻĻā§āϰāώā§āĻāĻŦā§āϝ: āĻāĻžāĻāĻžāϏā§āĻā§āϰāĻŋāĻĒā§āĻ āĻŦāύā§āϧ āĻĨāĻžāĻāϞ⧠āϞāĻŋāĻā§āĻ āĻā§āĻā§āϏāĻ āĻĒā§āϰāĻĻāϰā§āĻļāĻŋāϤ āĻšāϝāĻŧ
- āĻāĻŽā§āĻĒā§āĻā§ āĻŽā§āĻā§āϰāĻŋāϝāĻŧāĻžāϞ āĻĄāĻŋāĻāĻžāĻāύ 2
- āĻā§āĻāĻĒā§āϝāĻžāĻ āύā§āĻāĻŋāĻā§āĻļāύāĻā§ āύā§āĻāĻŋāĻā§āĻļāύ āĻāĻŽā§āĻĒā§āĻā§ āϏā§āĻĨāĻžāύāĻžāύā§āϤāϰ āĻāϰā§āύ
- āϝā§āĻāĻžāύ⧠āϰāĻžāĻā§āϝ āĻāϤā§āϤā§āϞāύ