Jetpack Compose 教學上課講義【從零開始學 Jetpack Compose 程式設計】Navigation 頁面跳轉
【從零開始學 Jetpack Compose 程式設計】
線上教學課程目錄: https://bit.ly/3JF4SFA
Youtube 課程播放清單:https://bit.ly/3tFjRbx
Udemy 線上課程:https://bit.ly/3MbVnhO
【從零開始學 Jetpack Compose 程式設計】
線上教學課程目錄: https://bit.ly/3JF4SFA
Youtube 課程播放清單:https://bit.ly/3tFjRbx
Udemy 線上課程:https://bit.ly/3MbVnhO
導航原則
https://developer.android.com/guide/navigation/navigation-principles
頁面跳轉範例
https://i.imgur.com/FUP0Voq.jpeg
依賴庫
implementation "androidx.navigation:navigation-compose:2.4.2"
Navigation 基本頁面切換
*先帶大家看 APP 畫面
package com.example.myapplication
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Demo()
}
}
}
sealed class Routes(val route: String) {
object APage : Routes("a_page")
object BPage : Routes("b_page")
object CPage : Routes("c_page")
}
@Composable
fun Demo(startDestination: String = Routes.APage.route) {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = startDestination
) {
composable(
Routes.APage.route
) {
APage(navController)
}
composable(
Routes.BPage.route
) {
BPage(navController)
}
composable(
Routes.CPage.route
) {
CPage(navController)
}
}
}
@Composable
fun APage(navController: NavHostController) {
BasePage("A 頁面內容", "前往") {
navController.navigate(Routes.BPage.route)
}
}
@Composable
fun BPage(navController: NavHostController) {
BasePage("B 頁面內容", "前往") {
navController.navigate(Routes.CPage.route)
}
}
@Composable
fun CPage(navController: NavHostController) {
BasePage("C 頁面內容", "返回") {
navController.navigateUp()
}
}
@Composable
fun BasePage(pageContent: String, btnContent: String, onClick: () -> Unit) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
pageContent,
fontSize = 30.sp,
modifier = Modifier.padding(bottom = 100.dp)
)
Button(
modifier = Modifier
.width(150.dp)
.height(100.dp),
onClick = {
onClick()
}
) {
Text(btnContent)
}
}
}
返回上一頁
//navigate 會 push 放入 Stack
//navController.navigate(Routes.APage.route)
//navigateUp 會把當下這一頁 pop 出來
navController.navigateUp
移除過場頁
類似註冊頁,註冊成功移除註冊相關流程頁面,即可以使用 popUpTo
A->B->C->A->A
popUpTo 移除過場頁,返回A頁,可以 pop up 移除B、C頁
A->B->C->A
popUpToInclusive = true 可以減少兩個 A 頁產生。
@Composable
fun CPage(navController: NavHostController) {
BasePage("C 頁面內容", "返回") {
navController.navigate(Routes.APage.route){
popUpTo(Routes.APage.route) {
inclusive = true
}
}
}
}
完整範例
package com.example.myapplication
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Demo()
}
}
}
sealed class Routes(val route: String) {
object APage : Routes("a_page")
object BPage : Routes("b_page")
object CPage : Routes("c_page")
}
@Composable
fun Demo(startDestination: String = Routes.APage.route) {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = startDestination
) {
composable(
Routes.APage.route
) {
APage(navController)
}
composable(
Routes.BPage.route
) {
BPage(navController)
}
composable(
Routes.CPage.route
) {
CPage(navController)
}
}
}
@Composable
fun APage(navController: NavHostController) {
BasePage("A 頁面內容", "前往") {
navController.navigate(Routes.BPage.route)
}
}
@Composable
fun BPage(navController: NavHostController) {
BasePage("B 頁面內容", "前往") {
navController.navigate(Routes.CPage.route)
}
}
@Composable
fun CPage(navController: NavHostController) {
BasePage("C 頁面內容", "返回") {
navController.navigate(Routes.APage.route){
popUpTo(Routes.APage.route) {
inclusive = true
}
}
}
}
@Composable
fun BasePage(pageContent: String, btnContent: String, onClick: () -> Unit) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
pageContent,
fontSize = 30.sp,
modifier = Modifier.padding(bottom = 100.dp)
)
Button(
modifier = Modifier
.width(150.dp)
.height(100.dp),
onClick = {
onClick()
}
) {
Text(btnContent)
}
}
}
Navigation 基本資料傳遞
package com.example.myapplication
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
NavGraph()
}
}
}
sealed class Routes(val route: String) {
object APage : Routes("a_page")
object BPage : Routes("b_page")
}
@Composable
fun NavGraph(startDestination: String = Routes.APage.route) {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = startDestination
) {
composable(
Routes.APage.route
) {
APage(navController)
}
composable(
Routes.BPage.route + "/{student_name}/{student_score}",
arguments = listOf(
navArgument("student_name") { type = NavType.StringType },
navArgument("student_score") { type = NavType.IntType },
),
) {
BPage(
navController,
it.arguments?.getString("student_name", "") ?: "",
it.arguments?.getInt("student_score") ?: 0,
)
}
}
}
@Composable
fun APage(navController: NavHostController) {
BasePage("A頁面內容", "前往") {
navController.navigate(Routes.BPage.route + "/HKT/100")
}
}
@Composable
fun BPage(navController: NavHostController, student_name: String, student_score: Int) {
BasePage("B頁面內容 \n 學生姓名:$student_name \n 成績:$student_score", "返回") {
// navController.navigate(Routes.APage.route)
navController.navigateUp()
}
}
@Composable
fun BasePage(pageContent: String, btnContent: String, onClick: () -> Unit) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
pageContent,
fontSize = 30.sp,
modifier = Modifier.padding(bottom = 100.dp)
)
Button(
modifier = Modifier
.width(150.dp)
.height(100.dp),
onClick = {
onClick()
}
) {
Text(btnContent)
}
}
}
Navigation 可選參數資料傳遞
package com.example.myapplication
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
NavGraph()
}
}
}
sealed class Routes(val route: String) {
object APage : Routes("a_page")
object BPage : Routes("b_page")
}
@Composable
fun NavGraph(startDestination: String = Routes.APage.route) {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = startDestination
) {
composable(
Routes.APage.route
) {
APage(navController)
}
composable(
Routes.BPage.route + "?student_name={student_name}&student_score={student_score}",
arguments = listOf(
navArgument("student_name") {
type = NavType.StringType
defaultValue = "資料錯誤"
},navArgument("student_score") {
type = NavType.IntType
defaultValue = -1
},
),
) {
BPage(
navController,
it.arguments?.getString("student_name", "資料錯誤") ?: "",
it.arguments?.getInt("student_score") ?: -1,
)
}
}
}
@Composable
fun APage(navController: NavHostController) {
BasePage("A頁面內容", "前往") {
// navController.navigate(Routes.BPage.route + "?student_name=HKT&student_score=100")
navController.navigate(Routes.BPage.route)
}
}
@Composable
fun BPage(navController: NavHostController, student_name: String, student_score: Int) {
BasePage("B頁面內容 \n 學生姓名:$student_name \n 成績:$student_score", "返回") {
// navController.navigate(Routes.APage.route)
navController.navigateUp()
}
}
@Composable
fun BasePage(pageContent: String, btnContent: String, onClick: () -> Unit) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
pageContent,
fontSize = 30.sp,
modifier = Modifier.padding(bottom = 100.dp)
)
Button(
modifier = Modifier
.width(150.dp)
.height(100.dp),
onClick = {
onClick()
}
) {
Text(btnContent)
}
}
}
傳遞整包資料
依賴庫
implementation 'com.google.code.gson:gson:2.8.6'
完整範例
package com.example.myapplication
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import com.google.gson.Gson
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
NavGraph()
}
}
}
data class Student(val name: String, val score: String)
sealed class Routes(val route: String) {
object APage : Routes("a_page")
object BPage : Routes("b_page")
}
@Composable
fun NavGraph(startDestination: String = Routes.APage.route) {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = startDestination
) {
composable(
Routes.APage.route
) {
APage(navController)
}
composable(
Routes.BPage.route + "/{student}",
arguments = listOf(
navArgument("student") { type = NavType.StringType }
),
) {
val defaultStudent = it.arguments?.getString("student", "") ?: ""
val student = Gson().fromJson(defaultStudent, Student::class.java)
BPage(
navController,
student
)
}
}
}
@Composable
fun APage(navController: NavHostController) {
val student = Student("HKT", "100")
val gson = Gson().toJson(student)
BasePage("A頁面內容", "前往") {
navController.navigate(Routes.BPage.route + "/$gson")
}
}
@Composable
fun BPage(navController: NavHostController, student: Student) {
BasePage("B頁面內容 \n 學生姓名:${student.name} \n 成績:${student.score}", "返回") {
navController.navigateUp()
}
}
@Composable
fun BasePage(pageContent: String, btnContent: String, onClick: () -> Unit) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
pageContent,
fontSize = 30.sp,
modifier = Modifier.padding(bottom = 100.dp)
)
Button(
modifier = Modifier
.width(150.dp)
.height(100.dp),
onClick = {
onClick()
}
) {
Text(btnContent)
}
}
}