Compose LazyColumn ๐ŸŒˆ

ํ‘ธ๋ฅธํ•˜๋Š˜ยท2022๋…„ 6์›” 30์ผ
2

์ปดํฌ์ฆˆ

๋ชฉ๋ก ๋ณด๊ธฐ
3/5
post-thumbnail

๐ŸŽ ํ˜„์—…์—์„œ ์™œ ๋งŽ์ด ์‚ฌ์šฉ๋˜๊ณ ์žˆ๋Š”๊ฐ€?

์•ˆ๋“œ๋กœ์ด๋“œ๋Š” ์˜›๋‚ ๋ถ€ํ„ฐ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋ฆฌ์ŠคํŠธ๋ฅผ View๋กœ ๋‚˜ํƒ€๋‚ ๋•Œ

  • XML ์— RecyclerView ์ƒ์„ฑ
  • RecylcerViewAdapter ์ƒ์„ฑ
  • itemView.xml ์ƒ์„ฑ
  • data class ์ƒ์„ฑ

์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ๋ถ€๋ถ„์ด ๋งŽ์•˜๋‹ค. ์ด๋Ÿฌํ•œ ๋ถ€๋ถ„์„ ํƒˆํ”ผํ•˜๊ณ ์ž Android ์—์„œ Layout ๋ถ€๋ถ„์ธ XML ๋ถ€๋ถ„๊ณผ Activity ๋ถ€๋ถ„์„ ํ•ฉ์ณ์„œ Jetpack Compose ๋ผ๋Š” ๊ธฐ์ˆ ์„ ๋งŒ๋“ค์–ด ๋ƒˆ๋‹ค.

๐ŸŽ Lazy(Column/Row/grides)

Row(ํ–‰)

  • ๋ฐ”๋ฒจ๋กœ์šฐ ์ž์„ธ ๊ธฐ์–ตํ•ด๋ผ Why?
    • ๋ฐ”๋ฒจ(๋ด‰) ๊ฐ€๋กœ๋กœ ๋ˆ•ํ˜€์ ธ์„œ ์˜ฌ๋ผ๊ฐ€๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค

Column(์—ด)

  • ์‚ฌ๋žŒ์ด ์—ด์ด๋‚˜๋ฉด ๋จธ๋ฆฌ๋ถ€ํ„ฐ ๋ฐœ๋๊นŒ์ง€ ๋‚œ๋‹ค
    • ์„ธ๋กœ๋ฅผ ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.

๐ŸŽ LazyColumn

LazyColumn ์€ item ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. item ํ•˜๋‚˜๊ฐ€ ์ž์‹ ์ปดํฌ์ €๋ธ”์— ๋Œ€์‘๋˜๋ฉฐ LazyColumnScope๋‚ด์—์„œ ๋‹ค์Œ์˜ item์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

item

LazyColumn ๋‚ด๋ถ€์— ์ปดํฌ์ €๋ธ”์„ ์ง์ ‘ ๋„ฃ๊ณ  ์‹ถ์„๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์†Œ๋“œ ์ž…๋‹ˆ๋‹ค. (LazyItemScope์— ์žˆ๋Š” ์ปดํฌ์ €๋ธ”์ด ํ•˜๋‚˜์˜ Item์œผ๋กœ ์ธ์‹๋œ๋‹ค)

fun item(key: Any? = null, content: @Composable LazyItemScope.() -> Unit)

items

์ปดํฌ์ €๋ธ”์„ ๋ฐ˜๋ณตํ•ด์„œ ๋‚˜ํƒ€๋‚ด๊ณ ์ž ํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค

fun items(
        count: Int,
        key: ((index: Int) -> Any)? = null,
        itemContent: @Composable LazyItemScope.(index: Int) -> Unit
    )

itmesIndexed

  1. ์‹ค์ œ ์ œํ’ˆ์„ ๊ฐœ๋ฐœํ•  ๋•Œ ๊ฐ€์žฅ ๋งŽ์ด ์“ฐ์ด๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค
  2. ์•„์ดํ…œ์œผ๋กœ Customํ•œ ํด๋ž˜์Šค์˜ ์„ค์ •์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
inline fun <T> LazyListScope.itemsIndexed(
    items: List<T>,
    noinline key: ((index: Int, item: T) -> Any)? = null,
    crossinline itemContent: @Composable LazyItemScope.(index: Int, item: T) -> Unit

์ฝ”๋“œ ๋ถ„์„

  • MessagesList() ์ปดํฌ์ €๋ธ” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ ๋‹ค
  • LazyColumn ์•ˆ์— First Item -> item(5) -> Last Item ์Œ“์ธ๋‹ค
  • ์œ„์— ๊ทธ๋ฆผ์ฒ˜๋Ÿผ ์ฐจ๊ณก ์ฐจ๊ณก ์Œ“์ธ๋‹ค.
  • itmes ํ•จ์ˆ˜ ๋‚ด๋ถ€์•ˆ์— ์žˆ๋Š” itmeContent๋ฅผ ์ด์šฉํ•˜์—ฌ index:Int ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MessageList()
        }
    }
}

@Composable
fun MessageList(){
    LazyColumn{
        item{
            Text("First item")
        }

        items(5){ index ->
            Text(text = "item :$index")
        }

        item{
            Text(text="Last Item")
        }
    }
}

๐ŸŽ Items / ItemsIndexed ์ ์šฉ ๋น„๊ต

๐Ÿ์ค€๋น„ ์ž‘์—…

  • Data class ์ƒ์„ฑ
  • Repository ์ƒ์„ฑ
  • CustomItem ์ƒ์„ฑ

Data Class

data class Person (
    val id : Int,
    val firstName : String,
    val lastName :String,
    val age :Int
        )

Repository

class PersonRepository {
    fun getAllData(): List<Person> {
        return listOf(
            Person(
                id = 0,
                firstName = "John",
                lastName = "Doe",
                age = 20
            ),
            Person(
                id = 1,
                firstName = "Maria",
                lastName = "Garcia",
                age = 21
            ),
            Person(
                id = 2,
                firstName = "James",
                lastName = "Johnson",
                age = 22
            ),
            Person(
                id = 3,
                firstName = "Michael",
                lastName = "Brown",
                age = 23
            ),
            Person(
                id = 4,
                firstName = "Robert",
                lastName = "Davis",
                age = 24
            ),
            Person(
                id = 5,
                firstName = "Jenifer",
                lastName = "Miller",
                age = 25
            ),
            Person(
                id = 6,
                firstName = "Sarah",
                lastName = "Lopez",
                age = 26
            ),
            Person(
                id = 7,
                firstName = "Charles",
                lastName = "Wilson",
                age = 27
            ),
            Person(
                id = 8,
                firstName = "Daniel",
                lastName = "Taylor",
                age = 28
            ),
            Person(
                id = 9,
                firstName = "Mark",
                lastName = "Lee",
                age = 29
            ),
        )
    }
}

CustomItem

@Composable
fun CustomItem(person: Person) {
    Row(
        modifier = Modifier
            .background(Color.LightGray)
            .fillMaxWidth()
            .padding(24.dp),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        Text(
            text = "${person.age}",
            color = Color.Black,
            fontSize = 50.sp,
            fontWeight = FontWeight.Bold
        )
        Text(
            text = person.firstName,
            color = Color.Black,
            fontSize = 30.sp,
            fontWeight = FontWeight.Normal
        )
        Text(
            text = person.lastName,
            color = Color.Black,
            fontSize = 30.sp,
            fontWeight = FontWeight.Normal
        )
    }
}


@Composable
@Preview
fun CustomItemPreview() {
    CustomItem(
        person = Person(
            id = 0,
            firstName = "John",
            lastName = "Doe",
            age = 20
        )
    )
}

๐Ÿ Items ๋„์ž… ํ–ˆ์„๋•Œ

์ฝ”๋“œ์„ค๋ช…

  • repositry ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค
  • getAllData() ๋ฅผ ํ™œ์šฉํ•ด Person(data.class) ์— ๋„˜๊ฒจ์„œ ๋ฆฌ์ŠคํŠธ ํ˜•ํƒœ๋กœ ๋งŒ๋“ ๋‹ค
  • LazyColumn ์•ˆ์— Padding์„ ๋„ฃ๋Š”๋‹ค
  • ๊ฐ ๋ฆฌ์ŠคํŠธ๋งˆ๋‹ค spaceBy๋ฅผ ๋„ฃ์–ด์„œ ๋ฆฌ์ŠคํŠธ ์•„์ดํ…œ์„ ๊ตฌ๋ถ„์‹œํ‚จ๋‹ค
  • items ์•ˆ์— List Person๋ฅผ ๋„ฃ๊ณ  CustomeItem์— ๋„ฃ๋Š”๋‹ค
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val personRepository  =PersonRepository()
            val getAllData = personRepository.getAllData()

            LazyColumn(contentPadding =  PaddingValues(all = 12.dp),
            verticalArrangement = Arrangement.spacedBy(12.dp)){
                items(items = getAllData){ person ->
                    CustomItem(person =  person)
                }
            }
        }
    }
}

๐Ÿ ItemsIndexed ๋„์ž… ํ–ˆ์„๋•Œ

key ๊ฐ’์„ ๋„ฃ๋Š”๋‹ค Why?

  • ๊ทธ ์ธ๋ฑ์Šค์˜ key ๊ฐ’์„ ์•Œ์•„์„œ ๋ณ€ํ™”๊ฐ€ ๋˜์—ˆ์„๋•Œ ๊ทธ ๋ฐ์ดํ„ฐ ๊ฐ’๋งŒ ๋ฆฌ์ปดํฌ์ฆˆ๊ฐ€ ๋˜์–ด ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์ž‡๋‹ค.
  • key ๊ฐ’์€ ์ฃผ๋กœ data.class ์— ์žˆ๋Š” id ๊ฐ’์„ ๊ฐ€์ ธ์™€์„œ ์‚ฌ์šฉํ•œ๋‹ค.
  • ์˜ˆ์ „ diffutil ์˜ ๊ฐœ๋…์ด๋ž‘ ๋น„์Šทํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val personRepository = PersonRepository()
            val getAllData = personRepository.getAllData()

            LazyColumn(
                contentPadding = PaddingValues(all = 12.dp),
                verticalArrangement = Arrangement.spacedBy(12.dp)
            ) {
                itemsIndexed(
                    items = getAllData,
                    key = { index ,person ->
                        person.id

                    }
                    ) { index, person ->
                    Log.d("MainActivity", index.toString())
                    CustomItem(person = person)
                }
            }
        }
    }
}

์ฝ”๋“œ ์„ค๋ช…

  • seticons List๋ฅผ ์ƒ์„ฑํ•œ๋‹ค
  • LazyColumn ์•ˆ์— padding์„ 12dp ๋ฅผ ์ค€๋‹ค
  • spaceBy๋ฅผ ํ•˜์—ฌ content์•ˆ์— ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ณต๊ฐ„์„ ๋ฒŒ๋ ค์ค€๋‹ค
  • stcikyHeader์— setcions ๊ฐ๊ฐ Header๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋„ฃ๋Š”๋‹ค
  • ๊ทธ์•ˆ์— ์ž„์˜๋กœ ์ƒ์„ฑํ•œ 10๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ๋Š”๋‹ค.
class MainActivity : ComponentActivity() {
    @ExperimentalFoundationApi
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val sections = listOf("A", "B", "C", "D", "E", "F", "G")

            LazyColumn(
                contentPadding = PaddingValues(all = 12.dp),
                verticalArrangement = Arrangement.spacedBy(12.dp)
            ) {
                sections.forEach { section ->
                    stickyHeader {
                        Text(
                            modifier = Modifier
                                .fillMaxSize()
                                .background(Color.Gray)
                                .padding(12.dp),
                            text = "Section $section"
                        )
                    }
                    items(10){
                        Text(text = "Item $it from the section $section",
                        modifier = Modifier.padding(12.dp))
                    }

                }
            }
        }
    }
}

๋‹ค์Œ์€ LazyRow

์ฐธ๊ณ ์ž๋ฃŒ

0๊ฐœ์˜ ๋Œ“๊ธ€