시배's Android

TiTi Side Project | TimeTable 컴포넌트 구현하기 본문

Android/TiTi Side Project

TiTi Side Project | TimeTable 컴포넌트 구현하기

si8ae 2024. 2. 7. 11:49

TdsTimeTable은 TiTI 프로젝트에서 사용되는 커스텀한 컴포넌트입니다. 이 컴포넌트는 사용자가 진행한 task에 대한 시간을 한눈에 파악할 수 있도록 도와주며, 각 시간대별로 진행한 task를 시각적으로 표현합니다.

 Canvas(
        modifier = modifier
            .drawWithContent {
                drawContent()
                drawGrid()
            },
    ) {
fun DrawScope.drawGrid() {
    val itemWidth = size.width / 7
    val itemHeight = size.height / 24

    var startX = 0f
    var startY = 0f

    repeat(7 * 24) { idx ->
        drawRect(
            color = Color(0x80626262),
            topLeft = Offset(
                x = startX,
                y = startY,
            ),
            size = Size(itemWidth, itemHeight),
            style = Stroke(width = 1f),
        )
        startX += itemWidth

        if (startX == itemWidth * 7) {
            startX = 0f
            startY += itemHeight
        }
    }
}

drawWithContent 함수를 사용하여 Canvas 내부에 추가적인 그리기 작업을 수행합니다. 이 함수를 사용하면 기존의 컨텐츠를 그리고, 이후에 추가적인 그리기 작업을 수행할 수 있습니다. 여기서는 drawContent()를 먼저 호출하고 격자를 그리는 drawGrid 함수를 호출하여 시간표의 격자를 drawContent()위에 그립니다.

  val itemWidth = size.width / 7
        val itemHeight = size.height / 24
        fontSize = (itemHeight / 5).sp

        repeat(24) { idx ->
            hour = (idx + 6).let { if (it >= 24) it - 24 else it }.toString()

            val startX = if (hour.length > 1) {
                itemWidth / 2 - hourTextLayoutResult.size.width
            } else {
                itemWidth / 2 - hourTextLayoutResult.size.width / 2
            }
            val startY = itemHeight * (idx + 0.5f) - hourTextLayoutResult.size.height / 2

            drawText(
                textMeasurer = hourTextMeasurer,
                text = hour,
                style = textStyle,
                topLeft = Offset(
                    x = startX,
                    y = startY,
                ),
            )
        }

시간 텍스트 그리기

시간별로 시간 텍스트를 그립니다. 각 시간의 텍스트를 그리고자 repeat 함수를 사용하여 24번의 반복 작업을 수행하며, 해당 시간을 나타내는 문자열을 계산하여 그려냅니다.

timeTableData.forEachIndexed { index, timeTableData ->
            val idx = (timeTableData.hour - 6).let { if (it < 0) it + 24 else it }
            val startX = itemWidth + itemWidth * 6 * timeTableData.start / 3600f
            val startY = itemHeight * idx
            val barWidth = itemWidth * 6 * (timeTableData.end - timeTableData.start) / 3600

            drawRoundRect(
                color = colors[index % colors.size],
                cornerRadius = CornerRadius(8.dp.toPx(), 8.dp.toPx()),
                topLeft = Offset(
                    x = startX,
                    y = startY,
                ),
                size = Size(
                    width = barWidth,
                    height = itemHeight,
                ),
            )
        }

작업 막대 그리기

각 작업에 대한 막대를 그립니다. timeTableData에 저장된 각 작업에 대한 정보를 순회하면서 해당 작업의 시작 시간과 종료 시간을 고려하여 막대를 그려냅니다. 각 작업에 대한 색상은 colors 리스트에서 가져와 순환합니다.