안드로이드/compose

[Compose] LazyColumn(LazyRow)과 Lazy를 중첩하는 법(Nested LazyColumn)

딩보 2023. 12. 14. 15:20

 

LazyColumn(LazyRow)란?

기존의 recyclerView를 대체하는 Compose UI이다.

 

항목의 수가 많거나 길이를 알 수 없는 목록을 특정 뷰로 반복하여 리스트로 보여줘야 할 때 사용한다.

 

recyclerView를 사용해본 사람들이라면 어댑터를 연결하고 ViewHolder를 생성하는 과정이 굉장히~~ 귀찮다.

그런데 LazyColumn을 사용하면 이 복잡한 과정이 모두 필요가 없다. 굳굳

 

 

사용법

@Composable
private fun courseLazyView(courses: List<Course>) {
    LazyColumn(
        modifier = Modifier
            .padding(start = 20.dp, top = 30.dp, end = 20.dp, bottom = 20.dp)
    ) {
        items(courses) { course ->
            courseView(course = course)
        }
    }
}

 

items의 인자로 List 변수를 주면 자동으로 생성해준다.

 

 

LazyColumn 안에 LazyColumn 넣는 법(Nested LazyColumn)

무턱대고 LazyColumn을 중첩한다면 에러가 발생한다. 공식 문서에서도 동일한 방향으로 스크롤뷰를 중첩할 수 없다고 명시되어 있다. 

그렇지만 내가 하고 싶은 것은 리스트를 값으로 갖는 리스트를 화면에 출력하는 것이다. 그럴 때의 해결책을 최대한 쉽게 소개해보려고 한다!

 

data class

data class Course(
    val course: String,
    val menu: List<String>
)


object DummyData {
	val dummyCourses = listOf(
    	Course(
            course = "A코스/한식",
            menu =listOf(
                "쌀밥 / 누룽지",
                "수제비국",
                "돈육장조림",
                "콩나물무침",
                "양반김",
                "배추김치",
                "모듬음료"
            )
        ),
        Course(
            course = "테이크아웃",
            menu =listOf(
                "미니꿀호떡",
                "견과류",
                "모듬음료"
            )
        )
    )
}

 

할려고 하는 것은 List<Course>를 뷰에 나타내는 것

 

구현(DayPlanView.kt 파일)

@Composable
private fun courseLazyView(courses: List<Course>) {
    LazyColumn(
        modifier = Modifier
            .padding(start = 20.dp, top = 30.dp, end = 20.dp, bottom = 20.dp)
    ) {
        items(courses) { course ->
            courseView(course = course)
        }
    }
}

@Composable
private fun courseView(course: Course) {
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .fillMaxHeight()
            .padding(bottom = 30.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        courseNameText(courseName = course.course)
        course.menu?.let { courseMenuLazy(menus = it) }
    }
}

@Composable
private fun courseNameText(courseName: String) {
    Text(
        text = courseName,
        color = colorResource(id = R.color.dark_gray),
        fontSize = FONT_SIZE.sp,
        fontWeight = FontWeight.Bold,
        modifier = Modifier.padding(bottom = 20.dp),
        textAlign = TextAlign.Center
    )
}

@Composable
private fun courseMenuLazy(menus: List<String>) {
    menus.forEach { menu ->
        Text(
            text = menu,
            color = Color.Black,
            fontSize = FONT_SIZE.sp
        )
    }
}

 

courseMenuLazy를 보면 view를 forEach를 통해 뿌려놓은 것을 확인할 수 있다. compose에서 제한하는 것은  같은 방향으로 스크롤뷰가 중첩되는 것이다. 사실 생각해보면 이미 상위 요소에서 스크롤이 구현되어 있는데 하위요소에서 스크롤을 만들 필요도 없을 뿐더러 그렇게 되면 스크롤이 꼬일 가능성도 크다.

 

그래서 이런 식으로 상위 요소에서 LazyColumn을 통해 스크롤 기능을 만들어준 후, 내부에는 forEach문을 통해 리스트의 요소를 반복하여 뷰를 생성해 주었다.

너무 쉽고 간단히 해결!

 

결과

짜잔