android:클래스와리스트를사용하기
클래스와리스트를사용하기
차이
문서의 선택한 두 판 사이의 차이를 보여줍니다.
| 다음 판 | 이전 판 | ||
| android:클래스와리스트를사용하기 [2024/08/08 20:05] – 만듦 이거니맨 | android:클래스와리스트를사용하기 [2024/08/09 00:02] (현재) – [4. 버튼 클릭 이벤트] 이거니맨 | ||
|---|---|---|---|
| 줄 16: | 줄 16: | ||
| var id : Int, | var id : Int, | ||
| var title : String, | var title : String, | ||
| - | var createdAt : LocalDate | + | var createdAt : LocalDateTime |
| ) | ) | ||
| fun getFakeTodo() : List< | fun getFakeTodo() : List< | ||
| return listOf< | return listOf< | ||
| - | Todo(1, "First todo", | + | Todo(1, "First todo", |
| - | Todo(2, " | + | Todo(2, " |
| - | Todo(3, "Third todo", | + | Todo(3, "Third todo", |
| - | Todo(4, "This is the last todo", | + | Todo(4, "This is the last todo", |
| ) | ) | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | ===== 화면에 출력하기 ===== | ||
| + | |||
| + | ==== 1. 간단하게 출력해보기 ===== | ||
| + | |||
| + | |||
| + | 위의 제목과 만든 날짜를 화면에 간단하게 출력해보자 | ||
| + | |||
| + | <file kotlin " | ||
| + | package com.dklaw.gogo2.pages | ||
| + | |||
| + | import androidx.compose.foundation.layout.Column | ||
| + | import androidx.compose.foundation.layout.Row | ||
| + | import androidx.compose.foundation.layout.fillMaxHeight | ||
| + | import androidx.compose.foundation.layout.padding | ||
| + | import androidx.compose.foundation.lazy.LazyColumn | ||
| + | import androidx.compose.foundation.lazy.itemsIndexed | ||
| + | import androidx.compose.material3.Text | ||
| + | import androidx.compose.runtime.Composable | ||
| + | import androidx.compose.ui.Modifier | ||
| + | import androidx.compose.ui.unit.dp | ||
| + | import com.dklaw.gogo2.database.Todo | ||
| + | import com.dklaw.gogo2.database.getFakeTodo | ||
| + | import java.time.format.DateTimeFormatter | ||
| + | |||
| + | @Composable | ||
| + | fun ContactsPage() { | ||
| + | |||
| + | val todoList = getFakeTodo() | ||
| + | |||
| + | Column(modifier = Modifier | ||
| + | .fillMaxHeight() | ||
| + | .padding(8.dp)) | ||
| + | { | ||
| + | LazyColumn( | ||
| + | content = { | ||
| + | itemsIndexed(todoList) { | ||
| + | index : Int, item : Todo -> | ||
| + | TodoItem(item = item) | ||
| + | } | ||
| + | } | ||
| + | ) | ||
| + | } | ||
| + | } | ||
| + | |||
| + | @Composable | ||
| + | fun TodoItem(item : Todo) { | ||
| + | val timeFormater : DateTimeFormatter = DateTimeFormatter.ofPattern(" | ||
| + | val nowString = item.createdAt.format(timeFormater) | ||
| + | |||
| + | Row { | ||
| + | Column { | ||
| + | Text(text = nowString) | ||
| + | Text(text = item.title) | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | |||
| + | |||
| + | </ | ||
| + | |||
| + | ===== 데이터 조작하기 ===== | ||
| + | |||
| + | ==== 1. Todo Manager ==== | ||
| + | |||
| + | <file kotlin " | ||
| + | package com.dklaw.gogo2.database | ||
| + | |||
| + | import java.time.LocalDateTime | ||
| + | |||
| + | object TodoManager { | ||
| + | |||
| + | private val todoList = mutableListOf< | ||
| + | |||
| + | fun getAllTodo() : List< | ||
| + | return todoList | ||
| + | } | ||
| + | |||
| + | fun addTodo(title : String) { | ||
| + | todoList.add(Todo(System.currentTimeMillis().toInt(), | ||
| + | } | ||
| + | |||
| + | fun deleteTodo(id : Int) { | ||
| + | todoList.removeIf{ | ||
| + | it.id == id | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | |||
| + | </ | ||
| + | |||
| + | |||
| + | ==== 2. view 모델 ==== | ||
| + | |||
| + | Todo Manager에서 한 데이터 작업을 뷰모델에서 다시 가져온다. | ||
| + | |||
| + | <file kotlin " | ||
| + | package com.dklaw.gogo2.database | ||
| + | |||
| + | import androidx.lifecycle.LiveData | ||
| + | import androidx.lifecycle.MutableLiveData | ||
| + | import androidx.lifecycle.ViewModel | ||
| + | |||
| + | class TodoViewModel: | ||
| + | |||
| + | private var _todoList = MutableLiveData< | ||
| + | val todoList : LiveData< | ||
| + | |||
| + | fun getAllTodo() { | ||
| + | _todoList.value = TodoManager.getAllTodo() | ||
| + | } | ||
| + | |||
| + | fun addTodo(title : String) { | ||
| + | TodoManager.addTodo(title) | ||
| + | getAllTodo() | ||
| + | } | ||
| + | |||
| + | fun deleteTodo(id : Int) { | ||
| + | TodoManager.deleteTodo(id) | ||
| + | getAllTodo() | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | ===== 뷰모델 동기화하기 ===== | ||
| + | |||
| + | ==== 1. 뷰모델을 상속하기 ==== | ||
| + | |||
| + | TodoListPage.kt 에서는 다음과 같이 뷰모델을 상속하여 뷰모델과 동기화할 준비를 한다. | ||
| + | |||
| + | <code kotlin> | ||
| + | @Composable | ||
| + | fun ContactsPage(viewModel: | ||
| + | |||
| + | val todoList by viewModel.todoList.observeAsState() | ||
| + | var inputText by remember { mutableStateOf("" | ||
| + | </ | ||
| + | |||
| + | |||
| + | <WRAP center round tip 90%> | ||
| + | observeAsState()함수를 사용하려면 livedata 디펜던시를 build.gradle.kts(module :app)에 추가해야 한다. | ||
| + | |||
| + | > implementation(" | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== 2. 뷰모델 공급자 지정 ==== | ||
| + | |||
| + | 다음과 같이 mainactivity에 공급자를 지정한다. | ||
| + | |||
| + | <code kotlin> | ||
| + | class MainActivity : ComponentActivity() { | ||
| + | |||
| + | |||
| + | override fun onCreate(savedInstanceState: | ||
| + | super.onCreate(savedInstanceState) | ||
| + | val todoViewModel = ViewModelProvider(this)[TodoViewModel:: | ||
| + | | ||
| + | enableEdgeToEdge() | ||
| + | setContent { | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== 3. 데이터가 없는 경우에 대한 예외 처리 ==== | ||
| + | |||
| + | TodoListPage.kt는 다음과 같이 수정한다. | ||
| + | |||
| + | fakeTodoList()가 아닌 실시간 Todo ViewModel을 사용하는 것이므로 처음에는 데이터 값이 없다. 따라서 이에 대한 예외를 처리해 줘야 한다. | ||
| + | |||
| + | <code kotlin> | ||
| + | todoList? | ||
| + | LazyColumn( | ||
| + | content = { | ||
| + | itemsIndexed(it) { | ||
| + | index : Int, item : Todo -> | ||
| + | TodoItem(item = item) | ||
| + | } | ||
| + | } | ||
| + | ) | ||
| + | }?: Text( | ||
| + | modifier = Modifier.fillMaxWidth(), | ||
| + | textAlign = TextAlign.Center, | ||
| + | text = "No Items yet", | ||
| + | fontSize = 16.sp | ||
| + | ) | ||
| + | </ | ||
| + | |||
| + | ==== 4. 버튼 클릭 이벤트 ==== | ||
| + | |||
| + | === 가. 추가하기 버튼 ==== | ||
| + | |||
| + | TodoListPage.kt에 다음과 같이 버튼 클릭 이벤트를 추가한다. | ||
| + | |||
| + | <code kotlin> | ||
| + | OutlinedTextField(value = inputText, onValueChange = { | ||
| + | inputText = it | ||
| + | }) | ||
| + | Button(onClick = { viewModel.addTodo(inputText); | ||
| + | Text(text = " | ||
| + | | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | === 나. 삭제하기 버튼 === | ||
| + | |||
| + | TodoListPage.kt에 다음과 같이 버튼 클릭 이벤트를 추가한다. | ||
| + | |||
| + | <code kotlin> | ||
| + | TodoItem(item = item, onDelete = {viewModel.deleteTodo(item.id)}) | ||
| + | </ | ||
| + | |||
| + | 위와 같이 onDelete라는 대리자를 지정했으므로 다음과 같이 TodoItem함수를 바꿔준다. | ||
| + | |||
| + | <code kotlin> | ||
| + | fun TodoItem(item : Todo, onDelete : ()-> Unit) { | ||
| + | |||
| + | (중략) | ||
| + | |||
| + | IconButton(onClick = onDelete ) { | ||
| + | (후략) | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== 다. 전체 코드 ==== | ||
| + | |||
| + | TodoListPage.kt의 전체 코드는 다음과 같다. | ||
| + | |||
| + | <file kotlin " | ||
| + | package com.dklaw.gogo2.pages | ||
| + | |||
| + | import androidx.compose.foundation.background | ||
| + | import androidx.compose.foundation.layout.Arrangement | ||
| + | import androidx.compose.foundation.layout.Column | ||
| + | import androidx.compose.foundation.layout.Row | ||
| + | import androidx.compose.foundation.layout.Spacer | ||
| + | import androidx.compose.foundation.layout.fillMaxHeight | ||
| + | import androidx.compose.foundation.layout.fillMaxWidth | ||
| + | import androidx.compose.foundation.layout.height | ||
| + | import androidx.compose.foundation.layout.padding | ||
| + | import androidx.compose.foundation.lazy.LazyColumn | ||
| + | import androidx.compose.foundation.lazy.itemsIndexed | ||
| + | import androidx.compose.foundation.shape.RoundedCornerShape | ||
| + | import androidx.compose.material3.Button | ||
| + | import androidx.compose.material3.Icon | ||
| + | import androidx.compose.material3.IconButton | ||
| + | import androidx.compose.material3.MaterialTheme | ||
| + | import androidx.compose.material3.OutlinedTextField | ||
| + | import androidx.compose.material3.Text | ||
| + | import androidx.compose.runtime.Composable | ||
| + | import androidx.compose.runtime.getValue | ||
| + | import androidx.compose.runtime.livedata.observeAsState | ||
| + | import androidx.compose.runtime.mutableStateOf | ||
| + | import androidx.compose.runtime.remember | ||
| + | import androidx.compose.runtime.setValue | ||
| + | import androidx.compose.ui.Alignment | ||
| + | import androidx.compose.ui.Modifier | ||
| + | import androidx.compose.ui.draw.clip | ||
| + | import androidx.compose.ui.graphics.Color | ||
| + | import androidx.compose.ui.res.painterResource | ||
| + | import androidx.compose.ui.text.style.TextAlign | ||
| + | import androidx.compose.ui.unit.dp | ||
| + | import androidx.compose.ui.unit.sp | ||
| + | import com.dklaw.gogo2.R | ||
| + | import com.dklaw.gogo2.database.Todo | ||
| + | import com.dklaw.gogo2.database.TodoViewModel | ||
| + | import java.time.format.DateTimeFormatter | ||
| + | |||
| + | @Composable | ||
| + | fun ContactsPage(viewModel: | ||
| + | |||
| + | val todoList by viewModel.todoList.observeAsState() | ||
| + | var inputText by remember { mutableStateOf("" | ||
| + | |||
| + | |||
| + | |||
| + | Column(modifier = Modifier | ||
| + | .fillMaxHeight() | ||
| + | .padding(8.dp), | ||
| + | { | ||
| + | Spacer(modifier = Modifier.height(32.dp)) | ||
| + | Text(text = " | ||
| + | |||
| + | Row (modifier = Modifier | ||
| + | .fillMaxWidth() | ||
| + | .padding(8.dp), | ||
| + | OutlinedTextField(value = inputText, onValueChange = { | ||
| + | inputText = it | ||
| + | }) | ||
| + | Button(onClick = { viewModel.addTodo(inputText) }) { | ||
| + | Text(text = " | ||
| + | inputText = "" | ||
| + | } | ||
| + | } | ||
| + | |||
| + | todoList? | ||
| + | LazyColumn( | ||
| + | content = { | ||
| + | itemsIndexed(it) { | ||
| + | index : Int, item : Todo -> | ||
| + | TodoItem(item = item, onDelete = {viewModel.deleteTodo(item.id)}) | ||
| + | } | ||
| + | } | ||
| + | ) | ||
| + | }?: Text( | ||
| + | modifier = Modifier.fillMaxWidth(), | ||
| + | textAlign = TextAlign.Center, | ||
| + | text = "No Items yet", | ||
| + | fontSize = 16.sp | ||
| + | ) | ||
| + | |||
| + | } | ||
| + | } | ||
| + | |||
| + | @Composable | ||
| + | fun TodoItem(item : Todo, onDelete : ()-> Unit) { | ||
| + | val timeFormater : DateTimeFormatter = DateTimeFormatter.ofPattern(" | ||
| + | val nowString = item.createdAt.format(timeFormater) | ||
| + | |||
| + | Row (modifier = Modifier | ||
| + | .fillMaxWidth() | ||
| + | .padding(8.dp) | ||
| + | .clip(RoundedCornerShape(16.dp)) | ||
| + | .background(MaterialTheme.colorScheme.primary) | ||
| + | .padding(16.dp), | ||
| + | verticalAlignment = Alignment.CenterVertically | ||
| + | ) { | ||
| + | Column (modifier = Modifier.weight(1f)){ | ||
| + | Text(text = nowString, fontSize = 10.sp, color = Color.LightGray) | ||
| + | Text(text = item.title, fontSize = 20.sp, color = Color.White) | ||
| + | } | ||
| + | IconButton(onClick = onDelete ) { | ||
| + | Icon(painter = painterResource(id = R.drawable.baseline_delete_24), | ||
| + | | ||
| + | } | ||
| + | } | ||
| } | } | ||
| </ | </ | ||
android/클래스와리스트를사용하기.1723115145.txt.gz · 마지막으로 수정됨: 저자 이거니맨
