LazyColumn 사용해보기

이윤설·2025년 3월 2일
0

안드로이드 연구소

목록 보기
27/33


코드

// namesList.kt

val names = listOf(
    "Kaylie Grant",
    "Leon Ventura",
    "Keanu Alvarado"
).groupBy {
    it.first()
}.toSortedMap()

-------------------------------------------------------------
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val namesList = names.map {
            Category(
                name = it.key.toString(),
                items = it.value
            )
        }
        setContent {
            CategorizedLazyColumnTheme {
                Surface(
                    color = MaterialTheme.colorScheme.background
                ) {
                    CategorizedLazyColumn(
                        categories = namesList
                    )
                }
            }
        }
    }
}

data class Category(
    val name: String,
    val items: List<String>
)

@Composable
private fun CategoryHeader(
    text: String,
    modifier: Modifier = Modifier
) {
    Text(
        text = text,
        fontSize = 16.sp,
        fontWeight = FontWeight.Bold,
        modifier = modifier
            .fillMaxWidth()
            .background(MaterialTheme.colorScheme.primaryContainer)
            .padding(16.dp)
    )
}

@Composable
private fun CategoryItem(
    text: String,
    modifier: Modifier = Modifier
) {
    Text(
        text = text,
        fontSize = 14.sp,
        modifier = modifier
            .fillMaxWidth()
            .background(MaterialTheme.colorScheme.background)
            .padding(16.dp)
    )
}

@Composable
private fun CategorizedLazyColumn(
    categories: List<Category>,
    modifier: Modifier = Modifier
) {
    LazyColumn(modifier) {
        categories.forEach { category ->
            stickyHeader {
                CategoryHeader(category.name)
            }
            items(category.items) { text ->
                CategoryItem(text)
            }
        }
    }
}

1. names 추출

names의 결과는 주어진 리스트를 첫 번째 문자(이름의 첫 글자)를 기준으로 그룹화한 뒤, 정렬된 Map이다.

groupBy { it.first() }는 이름의 첫 번째 문자(it.first())를 기준으로 각 이름을 그룹화한다.
그 후 toSortedMap()을 사용하여 이 그룹을 알파벳 순으로 정렬된 맵 형태로 변환한다.

코드

val names = listOf(
    "Kaylie Grant",
    "Leon Ventura",
    "Keanu Alvarado"
).groupBy {
    it.first()
}.toSortedMap()

단계별 동작

  1. groupBy { it.first() }:

    • it.first()는 각 이름의 첫 번째 문자를 가져온다.

    • groupBy는 이 첫 번째 문자를 기준으로 이름들을 그룹화한다.

    • "Kaylie Grant" → 첫 글자: "K"

    • "Leon Ventura" → 첫 글자: "L"

    • "Keanu Alvarado" → 첫 글자: "K"

    이로 인해 다음과 같이 그룹화된다.

    {
        K = ["Kaylie Grant", "Keanu Alvarado"],
        L = ["Leon Ventura"]
    }
  2. toSortedMap():

    • toSortedMap()은 결과를 키 기준으로 알파벳 순으로 정렬된 맵으로 변환한다.
    • KL보다 먼저 온다.

결과

{
    K = ["Kaylie Grant", "Keanu Alvarado"],
    L = ["Leon Ventura"]
}

2. names를 namesList로 변환

val namesList = names.map {
  Category(
    name = it.key.toString(),
     items = it.value
    )
}

여기서 map을 사용하면, 각 키(K, L), 값 리스트를 Category 객체로 변환한다.

  1. 첫 번째 변환
    • it.key = K, it.value = ["Kaylie Grant", "Keanu Alvarado"]
    • Category(name = "K", items = listOf("Kaylie Grant", "Keanu Alvarado"))
  2. 두 번째 변환
    • it.key = L, it.value = ["Leon Ventura"]
    • Category(name = "L", items = listOf("Leon Ventura"))

최종 namesList 결과

listOf(
    Category(name = "K", items = listOf("Kaylie Grant", "Keanu Alvarado")),
    Category(name = "L", items = listOf("Leon Ventura"))
)

3. LazyColumn 출력

@Composable
private fun CategorizedLazyColumn(
    categories: List<Category>,
    modifier: Modifier = Modifier
) {
    LazyColumn(modifier) {
        categories.forEach { category ->
            stickyHeader {
                CategoryHeader(category.name)
            }
            items(category.items) { text ->
                CategoryItem(text)
            }
        }
    }
}

이 함수는 이름 목록을 첫 글자별로 그룹화하여 리스트 형태로 표시한다.
LazyColumn을 사용하고,
각 카테고리의 헤더(첫 글자)는 스크롤 시 상단에 고정(stickyHeader) 되도록 구현되었다.

1. 이름을 첫 글자별로 그룹화한 categories 리스트를 받아서 LazyColumn을 사용하여 렌더링
2. 각 카테고리의 첫 글자를 stickyHeader로 추가하여 스크롤 시 상단에 고정
3. 각 카테고리에 속한 이름들을 CategoryItem으로 나열
4. 결과적으로 "K" 그룹에는 K로 시작하는 이름들이, "L" 그룹에는 L로 시작하는 이름들이 표시됨
5. 스크롤하면 현재 카테고리의 첫 글자가 상단에 고정되며, 다음 카테고리로 넘어갈 때 바뀜

LazyColumn, LazyRow, Sticky Header 개요

LazyColumn (수직 리스트)

개요

  • 세로 방향(수직) 리스트를 효율적으로 렌더링하는 Column 버전
  • RecyclerView와 비슷하지만 Compose 방식으로 구현됨
  • 내부적으로 항목이 화면에 나타날 때만 렌더링하여 성능 최적화

특징

스크롤 가능
많은 데이터를 효율적으로 관리
항목을 동적으로 추가 및 제거 가능


LazyRow

개요

  • 가로 방향(수평) 리스트를 효율적으로 렌더링하는 Row 버전
  • 스크롤 가능한 가로 리스트를 만들 때 사용

특징

가로 방향 스크롤 지원
스크롤 가능한 아이템이 필요할 때 사용
수평으로 많은 항목을 표시하는 경우 유용


Sticky Header (고정 헤더)

개요

  • 스크롤 시 특정 헤더를 상단에 고정하는 기능
  • LazyColumn과 함께 사용하여 리스트를 그룹화할 때 활용됨
  • 보통 카테고리별 목록을 표시할 때 유용

기본 사용법

LazyColumn {
    stickyHeader {
        Text("Header 1", modifier = Modifier.fillMaxWidth().background(Color.Gray))
    }
    items(listOf("Item A", "Item B", "Item C")) { item ->
        Text(text = item, modifier = Modifier.padding(16.dp))
    }
}

특징

스크롤 시 헤더가 상단에 고정됨
그룹화된 목록을 만들 때 유용
LazyColumn 내에서만 동작 (LazyRow에서는 지원하지 않음)


정리

기능LazyColumnLazyRowSticky Header
방향세로(Vertical)가로(Horizontal)LazyColumn 내에서 특정 헤더 고정
사용 예시일반 리스트, 뉴스 피드이미지 갤러리, 가로 스크롤 리스트카테고리별 목록, 연락처 리스트
스크롤위/아래 스크롤 가능좌/우 스크롤 가능헤더가 상단에 고정됨
주요 특징많은 데이터를 효율적으로 처리가로 스크롤 지원그룹화된 데이터 표시 시 유용

LazyRow, LazyColumn을 사용하면

화면에 보이는 항목만 렌더링하기 때문에,
메모리 낭비를 최소화하고 성능을 최적화할 수 있다!


참고한 영상 출처)
https://www.youtube.com/watch?v=XfYlRn_Jy1g&t=52s

profile
화려한 외면이 아닌 단단한 내면

0개의 댓글

관련 채용 정보