Row, Column을 활용하여 리스트를 만드는 것이 가능하나, 대부분의 상황에서 사용하는 것은 LazyRow, LazyColumn이다. 긴 리스트를 효율적으로 표시할 수 있고 스티키 헤더, 스크롤 위치 변경에 대응하는 등 다양한 기능을 제공하기 때문이다.
차량의 제조사와 이름을 담고 있는 문자열 배열과 함께 제조사의 로고 이미지를 표시하려면 로고 이미지들을 웹 서버로부터 다운로드받고 Image 컴포저블로 렌더링할 수 있다. 이때 이미지는 비동기적으로 다운로드되어 앱을 방해하지 말아야 한다.
이 작업을 하기 위해서는 이미지 로딩 라이브러리인 Coil을 사용해야 한다. Coil 라이브러리를 사용하면 특정 URL에 접근하여 이미지를 다운로드받고 앱에 렌더링하는 것이 가능하다. Coil을 사용하기 위해 다음 코드를 build.gradle에 추가한다.
implementation("io.coil-kt:coil-compose:1.3.2")
다음으로 이미지를 다운로드하고 Image 컴포넌트를 이용해 다운로드한 이미지를 표시하는 컴포저블 함수를 추가한다.
@Composable
fun ImageLoader(item: String) {
val url = "https://www.ebookfrenzy.com/book_examples/car_logos" +
item.substringBefore(" ") + "_logo.png"
}
@Composable
fun ImageLoader(item: String) {
val url = "https://www.ebookfrenzy.com/book_examples/car_logos" +
item.substringBefore(" ") + "_logo.png"
Image(
painter = rememberImagePainter(url),
contentDescription = "car image",
contentScale = ContentScale.Fit,
modifier = Modifier.size(75.dp)
)
}

하나의 Row에 이미지와 문자열을 표시하는 컴포저블을 만들어본다. elevation 효과와 둥근 모서리와 같은 커스터마이징을 위해 Row를 Card 안에 배치한다.
@Composable
fun MainScreen(itemArray: Array<out String>) {
MyCardListItem("Buick Roadmaster")
}
@OptIn(ExperimentalCoilApi::class)
@Composable
fun ImageLoader(item: String) {
val url = "https://www.ebookfrenzy.com/book_examples/car_logos/" +
item.substringBefore(" ") + "_logo.png"
Image(
painter = rememberImagePainter(url),
contentDescription = "car image",
contentScale = ContentScale.Fit,
modifier = Modifier.size(75.dp)
)
}
@Composable
fun MyCardListItem(item: String) {
Card(
modifier = Modifier
.padding(8.dp)
.fillMaxWidth(),
shape = RoundedCornerShape(10.dp),
elevation = CardDefaults.cardElevation(
defaultElevation = 5.dp
)
) {
Row(verticalAlignment = Alignment.CenterVertically) {
ImageLoader(item = item)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = item,
style = MaterialTheme.typography.headlineSmall,
modifier = Modifier.padding(8.dp)
)
}
}
}

이제는 리스트 전체의 아이템을 렌더링하도록 한다.
@Composable
fun MainScreen(itemArray: Array<out String>) {
LazyColumn() {
items(itemArray) { model ->
MyCardListItem(item = model)
}
}
}

리스트의 아이템을 클릭했을 때 토스트 메시지가 표시되도록 코드를 수정한다. 이를 위해 클릭 이벤트 핸들러 콜백 함수를 추가한다.
먼저 MainScreen에서 이벤트 핸들러 함수를 정의한다.
@Composable
fun MainScreen(itemArray: Array<out String>) {
val context = LocalContext.current
val onListItemClick = { text: String ->
Toast.makeText(
context,
text,
Toast.LENGTH_SHORT
).show()
}
LazyColumn() {
items(itemArray) { model ->
MyCardListItem(item = model, onItemClick = onListItemClick)
}
}
}
@Composable
fun MyCardListItem(item: String, onItemClick: (String) -> (Unit)) {
Card(
modifier = Modifier
.padding(8.dp)
.fillMaxWidth()
.clickable {onItemClick(item)},
shape = RoundedCornerShape(10.dp),
elevation = CardDefaults.cardElevation(
defaultElevation = 5.dp
)
) {
Row(verticalAlignment = Alignment.CenterVertically) {
ImageLoader(item = item)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = item,
style = MaterialTheme.typography.headlineSmall,
modifier = Modifier.padding(8.dp)
)
}
}
}
위 코드를 실행하면 다음과 같은 화면을 확인할 수 있다.
