今天主要建立詳細頁畫面,以及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 = ""
)
}
}
}
}
修改後畫面
詳細頁目前包含三個輸入框,分別是產品名稱、價格和訂閱類型,這些都是使用 OutlinedTextField
完成的。不過,由於訂閱類型需要下拉選單功能,因此這裡搭配了 ExposedDropdownMenuBox
和 ExposedDropdownMenu
來實現選單效果,來選擇不同的訂閱類型。
@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
}
)
}
}
}
}
}
}
畫面呈現
下拉選單呈現
明天預計建立首頁的ViewModel以及建立提供資料的Repository。