
package kr.co.fastcampus.part1.chapter5_3
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.Crossfade
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewmodel.compose.viewModel
import kr.co.fastcampus.part1.chapter5_3.ui.theme.LiveDataTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
LiveDataTheme() {
Surface(
modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background
) {
TopLevel()
}
}
}
}
}
class ToDoViewModel : ViewModel() {
private val _text = MutableLiveData("")
val text: LiveData<String> = _text
val setText: (String) -> Unit = {
_text.value = it
}
private val _rawToDoList = mutableStateListOf<ToDoData>()
private val _toDoList = MutableLiveData<List<ToDoData>>(this._rawToDoList)
val toDoList:LiveData<List<ToDoData>> = _toDoList
val onSubmit: (String) -> Unit = {
val key = (this._rawToDoList.lastOrNull()?.key ?: 0) + 1
this._rawToDoList.add(ToDoData(key, it))
_toDoList.value = ArrayList(this._rawToDoList)
_text.value = ""
}
val onEdit: (Int, String) -> Unit = { key, newText ->
val i = this._rawToDoList.indexOfFirst { it.key == key }
this._rawToDoList[i] = this._rawToDoList[i].copy(text = newText)
_toDoList.value = ArrayList(this._rawToDoList)
}
val onToggle: (Int, Boolean) -> Unit = { key, checked ->
val i = this._rawToDoList.indexOfFirst { it.key == key }
this._rawToDoList[i] = this._rawToDoList[i].copy(done = checked)
_toDoList.value = ArrayList(this._rawToDoList)
}
val onDelete: (Int) -> Unit = { key ->
val i = this._rawToDoList.indexOfFirst { it.key == key }
this._rawToDoList.removeAt(i)
_toDoList.value = ArrayList(this._rawToDoList)
}
}
@Composable
fun TopLevel(viewModel: ToDoViewModel = viewModel()) {
Scaffold {
Column {
ToDoInput(
text = viewModel.text.observeAsState("").value, onTextChange = {newText ->
viewModel.setText(newText)
}, onSubmit = viewModel.onSubmit
)
val items = viewModel.toDoList.observeAsState(emptyList()).value
LazyColumn {
items(items = items, key = { it.key }) { toDoData ->
ToDo(
toDoData = toDoData,
onEdit = viewModel.onEdit,
onToggle = viewModel.onToggle,
onDelete = viewModel.onDelete
)
}
}
}
}
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
LiveDataTheme {
TopLevel()
}
}
@Composable
fun ToDoInput(
text: String, onTextChange: (String) -> Unit, onSubmit: (String) -> Unit
) {
Row(modifier = Modifier.padding(8.dp)) {
OutlinedTextField(
value = text, onValueChange = onTextChange, modifier = Modifier.weight(1f)
)
Spacer(modifier = Modifier.size(8.dp))
Button(onClick = {
onSubmit(text)
}) {
Text("입력")
}
}
}
@Preview(showBackground = true)
@Composable
fun ToDoInputPreview() {
LiveDataTheme {
ToDoInput("테스트", {}, {})
}
}
@Composable
fun ToDo(
toDoData: ToDoData,
onEdit: (key: Int, text: String) -> Unit = { _, _ -> },
onToggle: (key: Int, checked: Boolean) -> Unit = { _, _ -> },
onDelete: (key: Int) -> Unit = {}
) {
var isEditing by remember { mutableStateOf(false) }
Card(
modifier = Modifier.padding(4.dp), elevation = 8.dp
) {
Crossfade(
targetState = isEditing,
) {
when (it) {
false -> {
Row(
modifier = Modifier.padding(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = toDoData.text, modifier = Modifier.weight(1f)
)
Text("완료")
Checkbox(checked = toDoData.done, onCheckedChange = { checked ->
onToggle(toDoData.key, checked)
})
Button(onClick = { isEditing = true }) {
Text("수정")
}
Spacer(modifier = Modifier.size(4.dp))
Button(onClick = { onDelete(toDoData.key) }) {
Text("삭제")
}
}
}
true -> {
Row(
modifier = Modifier.padding(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
val (text, setText) = remember { mutableStateOf(toDoData.text) }
OutlinedTextField(
value = text, onValueChange = setText, modifier = Modifier.weight(1f)
)
Spacer(modifier = Modifier.size(8.dp))
Button(onClick = {
isEditing = false
onEdit(toDoData.key, text)
}) {
Text("완료")
}
}
}
}
}
}
}
@Preview(showBackground = true)
@Composable
fun ToDoPreview() {
LiveDataTheme {
ToDo(ToDoData(1, "nice", true))
}
}
data class ToDoData(
val key: Int, val text: String, val done: Boolean = false
)