iT邦幫忙

2024 iThome 鐵人賽

DAY 25
0
Mobile Development

從零開始學習 Jetpack Compose系列 第 25

從零開始學習 Jetpack Compose Day24 - 專案實作(2)詳細頁畫面建置

  • 分享至 

  • xImage
  •  

今天主要建立詳細頁畫面,以及navigation補上傳遞參數。

主畫面

首先我將主畫面抽離到另一個檔案中比較好閱讀,並在 floatingActionButton 傳遞空 ID 給詳細頁,因為詳細頁會根據條件分為新增或編輯。若是新增則不帶 ID,若是編輯則帶上該 ID。此外,清單的呈現也進行了調整,跳轉至詳細頁會帶上該 ID。昨天測試時,發現清單排版異常,後來發現是因為 Modifier 設置錯誤。修正後,清單顯示恢復正常。

HomeScreen.kt

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HomeScreen(navController: NavController? = null, modifier: Modifier = Modifier) {
    val application = LocalContext.current.applicationContext as AppApplication
    val list = application.list
    Scaffold(
        topBar = {
            CenterAlignedTopAppBar(
                title = {
                    Text("ITHelp Side Project")
                },
                navigationIcon = {
                    IconButton(onClick = { }) {
                        Icon(
                            imageVector = Icons.Filled.Menu,
                            contentDescription = ""
                        )
                    }
                },
                actions = {
                    IconButton(onClick = { }) {
                        Icon(
                            imageVector = Icons.Filled.AccountCircle,
                            contentDescription = ""
                        )
                    }
                }
            )
        },
        floatingActionButton = {
            FloatingActionButton(onClick = {
                navController?.navigate("detail/{id}")
            }) {
                Icon(Icons.Default.Add, contentDescription = "")
            }
        }
    ) { innerPadding ->
        LazyColumn(
            modifier = Modifier
                .padding(innerPadding)
                .fillMaxWidth()
                .fillMaxHeight()
        ) {
            items(list) { item: SubscriptionViewData ->
                SubscriptionItem(
                    modifier = modifier,
                    navController = navController,
                    data = item
                )
            }
        }
    }
}
@Composable
fun SubscriptionItem(
    modifier: Modifier,
    navController: NavController?,
    data: SubscriptionViewData
) {
    Card(
        modifier = Modifier.padding(16.dp)
    ) {
        Row(
            verticalAlignment = Alignment.CenterVertically,
            modifier = Modifier
                .fillMaxWidth()
                .padding(horizontal = 16.dp, vertical = 8.dp)
        ) {
            Image(
                painter = painterResource(R.drawable.ic_launcher_background),
                contentDescription = "",
                modifier = Modifier
                    .height(32.dp)
                    .width(32.dp)
            )
            Column(
                modifier = Modifier
                    .weight(1f)
                    .padding(8.dp)
            ) {
                Text(
                    text = data.name,
                    fontSize = 24.sp
                )
                Text(
                    text = "$ ${data.price}/${data.cycle}"
                )
            }
            IconButton(onClick = {
                navController?.navigate("detail/${data.id}")
            }) {
                Icon(
                    imageVector = Icons.AutoMirrored.Filled.ArrowForward,
                    contentDescription = ""
                )
            }

        }
    }
}

修改後畫面
https://raw.githubusercontent.com/jian-fu-hung/ithelp-2024/refs/heads/main/Images/Day24/%E6%88%AA%E5%9C%96%202024-10-09%20%E6%99%9A%E4%B8%8A11.20.51.png

詳細頁

詳細頁目前包含三個輸入框,分別是產品名稱、價格和訂閱類型,這些都是使用 OutlinedTextField 完成的。不過,由於訂閱類型需要下拉選單功能,因此這裡搭配了 ExposedDropdownMenuBoxExposedDropdownMenu 來實現選單效果,來選擇不同的訂閱類型。

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DetailScreen(productId: String, navController: NavController? = null, modifier: Modifier = Modifier) {
    val application = LocalContext.current.applicationContext as AppApplication
    val item = application.list.find { it.id == productId }
    Scaffold(
        topBar = {
            CenterAlignedTopAppBar(
                title = {
                    Text(item?.name ?: "新增產品")
                },
                navigationIcon = {
                    IconButton(onClick = {
                        navController?.popBackStack()
                    }) {
                        Icon(
                            imageVector = Icons.AutoMirrored.Filled.ArrowBack,
                            contentDescription = ""
                        )
                    }
                },
                actions = {

                }
            )
        }
    ) { innerPadding ->
        Column(
            modifier = Modifier.padding(innerPadding).fillMaxWidth().fillMaxHeight()
        ) {
            val options = listOf("月訂閱", "年訂閱", "一次性購買")
            var selectedOptionText by remember { mutableStateOf(options[0]) }
            var product by remember { mutableStateOf(item?.name ?: "") }
            var price by remember { mutableStateOf(item?.price ?: "") }
            var expanded by remember { mutableStateOf(false) }

            OutlinedTextField(
                value = product,
                onValueChange = {product = it},
                label = {
                    Text("訂閱產品")
                },
                leadingIcon = {
                    Icon(
                        imageVector = Icons.Outlined.Face,
                        contentDescription = ""
                    )
                },
                modifier = Modifier.fillMaxWidth().padding(10.dp)
            )

            OutlinedTextField(
                value = price,
                onValueChange = {price = it},
                label = {
                    Text("價格")
                },
                prefix = {
                    Text("$")
                },
                leadingIcon = {
                    Icon(
                        imageVector = Icons.Outlined.Face,
                        contentDescription = ""
                    )
                },
                keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal),
                modifier = Modifier.fillMaxWidth().padding(10.dp)
            )

            ExposedDropdownMenuBox(
                expanded = expanded,
                onExpandedChange = {
                    expanded = !expanded
                }
            ) {
                OutlinedTextField(
                    value = selectedOptionText,
                    readOnly = true,
                    onValueChange = {selectedOptionText = it},
                    label = {
                        Text("訂閱類型")
                    },
                    leadingIcon = {
                        Icon(
                            imageVector = Icons.Outlined.Face,
                            contentDescription = ""
                        )
                    },
                    keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal),
                    modifier = Modifier.fillMaxWidth().padding(10.dp).menuAnchor(),
                    trailingIcon = {
                        ExposedDropdownMenuDefaults.TrailingIcon(
                            expanded = expanded
                        )
                    },
                )
                ExposedDropdownMenu(
                    expanded = expanded,
                    onDismissRequest = {
                        expanded = false
                    }
                ) {
                    options.forEach { selectionOption ->
                        DropdownMenuItem(
                            text = {
                                Text(text = selectionOption)
                            },
                            onClick = {
                                selectedOptionText = selectionOption
                                expanded = false
                            }
                        )
                    }
                }
            }
        }
    }
}

畫面呈現
https://raw.githubusercontent.com/jian-fu-hung/ithelp-2024/refs/heads/main/Images/Day24/%E6%88%AA%E5%9C%96%202024-10-09%20%E6%99%9A%E4%B8%8A11.27.58.png

https://raw.githubusercontent.com/jian-fu-hung/ithelp-2024/refs/heads/main/Images/Day24/%E6%88%AA%E5%9C%96%202024-10-09%20%E6%99%9A%E4%B8%8A11.28.11.png

下拉選單呈現
https://raw.githubusercontent.com/jian-fu-hung/ithelp-2024/refs/heads/main/Images/Day24/%E6%88%AA%E5%9C%96%202024-10-09%20%E6%99%9A%E4%B8%8A11.28.25.png

明天預計建立首頁的ViewModel以及建立提供資料的Repository。


上一篇
從零開始學習 Jetpack Compose Day23 - 專案實作(1)畫面建置
下一篇
從零開始學習 Jetpack Compose Day25 - 專案實作(3)主畫面 ViewModel 建立
系列文
從零開始學習 Jetpack Compose30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言