0

I am developing on moving the list(item) in LazyColumn Composable using Jetpack Compose and Kotlin.

The app I am implementing is the TodoList app, and if I explain the function, the item includes text and checkbox composable, and the position of the list (item) changes depending on the value (true, false). If the value of the check box changes to false -> true, the list (item) moves to the bottom of the sticky header to which it belongs, and if the value of the check box changes to true -> false, the list (item) moves to the original position of the sticky header to which it belongs.

The problem with the code I implemented is that if the value of the check box changes to false -> true, the list (item) is normally implemented to move to the bottom of the sticky header to which it belongs, but if the value of the check box changes to true -> false, the list (item) is not to the original place of the sticky header to which it belongs.

If the value of the check box changes to true -> false, it is too difficult to implement the function of moving the list(item) to the original position of the sticky header to which it belongs, so I ask the developers.

How can I fix it?

  • Checkbox value: false -> true => onCheckedUpdateTodo()
  • Checkbox value: true -> false => onUnCheckedUpdateTodo()

UpdateTodo

fun updateTodo(
    token: String,
    year: String,
    month: String,
    day: String,
    title: String,
    done: Boolean,
    description: String,
    color: String,
    time: String,
    id: String,
    response: (UpdateTodoResponse?) -> Unit,
) {

    var updateTodoResponse: UpdateTodoResponse? = null

    var retrofit = Retrofit.Builder().baseUrl("https://plotustodo-ctzhc.run.goorm.io/")
        .addConverterFactory(GsonConverterFactory.create()).build()

    var updateTodoRequest: UpdateTodoRequest = retrofit.create(UpdateTodoRequest::class.java)

    updateTodoRequest.requestUpdateTodo(
        token,
        id,
        UpdateTodo(year, month, day, title, done, description, color, time)
    )
        .enqueue(object : Callback<UpdateTodoResponse> {

            // 실패 했을때
            override fun onFailure(call: Call<UpdateTodoResponse>, t: Throwable) {
                Log.e("updateTodo", t.message.toString())
            }

            // 성공 했을때
            override fun onResponse(
                call: Call<UpdateTodoResponse>,
                response: Response<UpdateTodoResponse>,
            ) {

                if (response.isSuccessful) {
                    updateTodoResponse = response.body()

                    response(updateTodoResponse)

                    Log.d("updateTodo", "token : " + MyApplication.prefs.getData("token", ""))
                    Log.d("updateTodo", "resultCode : " + updateTodoResponse?.resultCode)
                } else {
                    Log.e("updateTodo", "resultCode : " + response.body())
                    Log.e("updateTodo", "code : " + response.code())
                }
            }
        })
}

readTodo

fun readTodo(
    token: String,
    year: String,
    month: String,
    day: String,
    response: (ReadTodoResponse?) -> Unit,
) {

    var readTodoResponse: ReadTodoResponse? = null

    var retrofit = Retrofit.Builder().baseUrl("https://plotustodo-ctzhc.run.goorm.io/")
        .addConverterFactory(GsonConverterFactory.create()).build()

    var readTodoRequest: ReadTodoRequest = retrofit.create(ReadTodoRequest::class.java)

    readTodoRequest.requestReadTodo(token, year, month, day)
        .enqueue(object : Callback<ReadTodoResponse> {

            //실패할 경우
            override fun onFailure(call: Call<ReadTodoResponse>, t: Throwable) {
                Log.e("readTodo", t.message.toString())
            }

            //성공할 경우
            override fun onResponse(
                call: Call<ReadTodoResponse>,
                response: Response<ReadTodoResponse>,
            ) {
                readTodoResponse = response.body()

                response(readTodoResponse)

                Log.d("readTodo", "token : " + MyApplication.prefs.getData("token", ""))
                Log.d("readTodo", "resultCode : " + readTodoResponse?.resultCode)
                Log.d("readTodo", "data : " + readTodoResponse?.data)
            }
        })
}

RToDoResponse

data class RToDoResponse(
    val id: String,
    val writer: String,
    val year: String,
    val month: String,
    val day: String,
    val title: String,
    val description: String,
    val done: Boolean,
    val time: String,
    val color: Int
)

TodoItem(One Item) & TodoList(LazyColumn)

@Composable
fun TodoItem(
    Todo: RToDoResponse,
    onTodoItemClick: (RToDoResponse) -> Unit,
    onCheckedUpdateTodo: () -> Unit,
    onUnCheckedUpdateTodo: () -> Unit
) {
    var checked by rememberSaveable { mutableStateOf(Todo.done) }
    val token = "Token ${MyApplication.prefs.getData("token", "")}"
    var done by remember { mutableStateOf(false) }

    LaunchedEffect(
        key1 = Unit,
        block = {
            done = Todo.done

            if (checked) {
                done = true
                checked = true
                updateTodo(token,
                    Todo.year,
                    Todo.month,
                    Todo.day,
                    Todo.title,
                    done,
                    Todo.description,
                    Todo.color.toString(),
                    Todo.time,
                    Todo.id,
                    response = {
                        onCheckedUpdateTodo()
                    })
            }
        }
    )

    Card(colors = CardDefaults.cardColors(Color.White),
        shape = RoundedCornerShape(8.dp),
        modifier = Modifier
            .fillMaxWidth()
            .height(50.dp)
            .clickable {
                onTodoItemClick(Todo)
            }) {
        Row(
            modifier = Modifier.padding(start = 7.dp, top = 15.dp, bottom = 15.dp),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.Center
        ) {
            Checkbox(
                checked = checked,
                onCheckedChange = {
                    checked = it
                    if (checked) {
                        done = true
                        checked = true
                        updateTodo(token,
                            Todo.year,
                            Todo.month,
                            Todo.day,
                            Todo.title,
                            done,
                            Todo.description,
                            Todo.color.toString(),
                            Todo.time,
                            Todo.id,
                            response = {
                                onCheckedUpdateTodo()
                            })
                    } else {
                        done = false
                        checked = false
                        updateTodo(token,
                            Todo.year,
                            Todo.month,
                            Todo.day,
                            Todo.title,
                            done,
                            Todo.description,
                            Todo.color.toString(),
                            Todo.time,
                            Todo.id,
                            response = {
                                onUnCheckedUpdateTodo()
                            })
                    }
                }, colors = CheckboxDefaults.colors(
                    when (Todo.color) {
                        1 -> Color(0xffFFB4B4)
                        2 -> Color(0xffFFDCA8)
                        3 -> Color(0xffB1E0CF)
                        4 -> Color(0xffB7D7F5)
                        5 -> Color(0xffFFB8EB)
                        6 -> Color(0xffB6B1EC)
                        else -> Color.Black
                    }
                )

            )
            Text(text = Todo.title, fontSize = 13.sp, fontStyle = FontStyle.Normal)
        }
    }
}

@Composable
fun TodoItemList(
    Todo: List<RToDoResponse>,
    todoList: MutableList<RToDoResponse>,
    onTodoItemClick: (RToDoResponse) -> Unit,
) {

    val token = "Token ${MyApplication.prefs.getData("token", "")}"


    LazyColumn(verticalArrangement = Arrangement.spacedBy(6.dp)) {

        val grouped = Todo.groupBy { it.color }

        grouped.forEach { (header, items) ->

            stickyHeader {
                Row(
                    modifier = Modifier.fillMaxWidth(),
                    verticalAlignment = Alignment.CenterVertically
                ) {

                    Button(
                        modifier = Modifier.size(9.dp),
                        onClick = { /*TODO*/ },
                        enabled = false,
                        content = {},
                        colors = ButtonDefaults.buttonColors(
                            disabledContainerColor = when (header) {
                                1 -> Color(0xffFFB4B4)
                                2 -> Color(0xffFFDCA8)
                                3 -> Color(0xffB1E0CF)
                                4 -> Color(0xffB7D7F5)
                                5 -> Color(0xffFFB8EB)
                                6 -> Color(0xffB6B1EC)
                                else -> Color.Black
                            }
                        )
                    )

                    Spacer(modifier = Modifier.padding(horizontal = 5.dp))

                    Text(
                        text = "그룹 $header",
                        fontWeight = FontWeight.Bold,
                        fontSize = 13.sp,
                        lineHeight = 17.sp
                    )
                }
            }
            items(items = items, key = { Todo -> Todo.id }) { item ->

                val dismissState = androidx.compose.material.rememberDismissState()
                val dismissDirection = dismissState.dismissDirection
                val isDismissed = dismissState.isDismissed(DismissDirection.EndToStart)
                if (isDismissed && dismissDirection == DismissDirection.EndToStart) {
                    deleteTodo(token, item.id, response = {
                        todoList.remove(item)
                        readTodo(token, year = item.year, month = item.month, day = item.day) {
                            todoList.clear()
                            for (i in it!!.data) {
                                todoList.add(i)
                            }
                        }
                    })
                }

                androidx.compose.material.SwipeToDismiss(state = dismissState,
                    background = { DeleteBackground() },
                    directions = setOf(DismissDirection.EndToStart),
                    dismissContent = {
                        TodoItem(Todo = item,
                            onTodoItemClick = { onTodoItemClick(it) },
                            onCheckedUpdateTodo = {
                                todoList.removeAll {
                                    it.id == item.id
                                }
                                todoList.add(item)
                            }, onUnCheckedUpdateTodo = {
todoList.removeAll { it.id == item.id }
                                    todoList.add(
                                        todoList.indexOfFirst { !it.done || it.id == item.id },
                                        item.copy(done = false))
                                }
                            })
                    },
                    dismissThresholds = {
                        androidx.compose.material.FractionalThreshold(fraction = 0.2f)
                    })
            }
        }
    }
}
박종준
  • 125
  • 1
  • 2
  • 10

0 Answers0