這裡就是第一部分的完結了,現在要透過將App的介面做出來來熟悉與複習
雖然說我們還沒有學到如何切換頁面與跨頁面保留資料,但是這不妨礙我們先把畫面給做出來,之後再結合起來
這部分會用到很多的container,還有基本的UI元素
首先建一個資料夾,我這邊是把清單和清單組瀏覽分開,讓項目結構更清晰:
在day3時候,我們的清單是分組的,所以這邊也這麼分
data class TodoItem(var title: String, var content: String, var group: String, var done: Boolean = false)
val todoItems = listOf<TodoItem>(
TodoItem("a", "content", "a list"),
TodoItem("b", "empty", "a list", true),
TodoItem("c", "nothing", "b list", true),
TodoItem("d", "void", "b list"),
TodoItem("e", "vacant", "a list"),
)
先建立一個清單用作測試
首先,我們明顯需要一個LazyColumn
@Composable
fun TodoGroups() {
val groupList = todoItems.groupBy {
it.group
}.toList()
LazyColumn(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
contentPadding = PaddingValues(10.dp, 8.dp),
verticalArrangement = Arrangement.spacedBy(5.dp)
) {
items(groupList) { group->
GroupItem(group)
}
}
}
在用group將零散的todoItems組合起來後,就可以準確地對groupList展開了
但是我們還需要一個可以展示Group的GroupItem
@Composable
fun GroupItem(group: Pair<String, List<TodoItem>>) {
val undoneAmount = group.second.count { !it.done }
val totalAmount = group.second.size
Column(
modifier = Modifier.fillMaxWidth()
.background(Color.Gray, RoundedCornerShape(5.dp)),
) {
Text(
group.first,
fontWeight = FontWeight.Bold,
fontSize = 20.sp,
modifier = Modifier.padding(10.dp, 3.dp)
)
Text(
"$undoneAmount/$totalAmount tasks undone",
fontSize = 14.sp,
modifier = Modifier.padding(10.dp, 3.dp)
)
}
}
根據觀察,它是column與文字的組合而已
完成後預覽一下,雖然顏色不對,但配置沒問題
這邊一樣,用LazyColumn套Item
@Composable
fun TodoDisplay(groupTodos: List<TodoItem>) {
LazyColumn(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(6.dp)
) {
items(todoItems) {
TodoItemBox(it)
}
}
}
@Composable
fun TodoItemBox(todoItem: TodoItem) {
Row(
modifier = Modifier.fillMaxWidth(0.85f),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
todoItem.title,
modifier = Modifier.weight(1f),
fontSize = 18.sp,
fontWeight = FontWeight.Bold
)
Text(
todoItem.content,
modifier = Modifier.weight(2f),
fontSize = 14.sp,
fontWeight = FontWeight.Light
)
Checkbox(
checked = todoItem.done,
onCheckedChange = {},
)
}
}
再另外建立一個資料夾,並在裡面建立一個負責輸入介面UI的檔案
從之前的prototype規劃,我們應該使用Column搭配幾個輸入框與一個submit button
@Composable
fun InputPage() {
val groupNameList = listOf("a list", "b list")
var title by remember { mutableStateOf("") }
var content by remember { mutableStateOf("") }
var group by remember { mutableStateOf(groupNameList.first()) }
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(20.dp, Alignment.CenterVertically),
horizontalAlignment = Alignment.CenterHorizontally
) {
TextField(
value = title,
onValueChange = {
title = it
},
modifier = Modifier.fillMaxWidth(0.8f),
singleLine = true,
label = {
Text("Title")
}
)
TextField(
value = content,
onValueChange = {
content = it
},
modifier = Modifier.fillMaxWidth(0.8f),
label = {
Text("Content")
}
)
DropDownSelector(
groupNameList,
group,
) { group = it }
Button(
onClick = {}
) {
Text("Submit")
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DropDownSelector(
menu: List<String>,
currentDisplay: String,
onChosen: (String) -> Unit
) {
var expanded by remember { mutableStateOf(false) }
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = { expanded = !expanded }
) {
TextField(
value = currentDisplay,
onValueChange = {},
readOnly = true,
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded) },
modifier = Modifier
.menuAnchor(MenuAnchorType.PrimaryNotEditable)
.fillMaxWidth(0.8f),
singleLine = true,
label = {
Text("Group name")
}
)
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
menu.forEach { option ->
DropdownMenuItem(
text = { Text(option) },
onClick = {
onChosen(option)
expanded = false
}
)
}
}
}
}
這是Material3的一個實驗性UI,所以要再開頭加一個annotaion@OptIn(ExperimentalMaterial3Api::class)
,是原生的選單實現
menuAnchor(MenuAnchorType.PrimaryNotEditable)
是針對ExposedDropdownMenu的快速modifier設定包,讓TextField可以接管他的狀態trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded) }
結尾的Icon
這樣子主要的幾個介面就寫完了,後面有整頁設計的地方不會再給出整段程式碼,但是這個專案應該會在結束前能在Github上看到,剩下的大概只剩下了增加新的group和設定頁面