๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“ฑ| Android/๐Ÿš€ | Jetpack

[Android, Kotlin] Compose UI ์ •๋ฆฌ(5)

by immgga 2023. 3. 13.

์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” compose UI ๊ณต๋ถ€ํ–ˆ๋˜ ๋‚ด์šฉ์„ ๋„์ ์—ฌ๋ณด๊ฒ ๋‹ค.

 

์ด์ „ ํฌ์ŠคํŒ…

https://rkdrkd-history.tistory.com/44

 

[Android, Kotlin] Compose UI ์ •๋ฆฌ(4)

์ง€๋‚œ ํฌ์ŠคํŒ… https://rkdrkd-history.tistory.com/43 [Android, Kotlin] Compose UI ์ •๋ฆฌ(3) ์ด์ „ ํฌ์ŠคํŒ… https://rkdrkd-history.tistory.com/42 [Android, Kotlin] Compose UI ์ •๋ฆฌ(2) ์ง€๋‚œ ํฌ์ŠคํŒ… https://rkdrkd-history.tistory.com/41 [Android, Kot

rkdrkd-history.tistory.com

 

์ด๋ฒˆ์— ์ •๋ฆฌํ•  ๋‚ด์šฉ์€ compose์—์„œ glide ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

 

๋งŒ๋“ค์–ด๋ณผ ์˜ˆ์ œ๋Š” lazyColumn(recyclerView)๋ฅผ ์ด์šฉํ•ด ํ”„๋กœํ•„ ์‚ฌ์ง„๊ณผ ์œ ์ € ์ด๋ฆ„, ์„ค๋ช…์„ ๋„ฃ์–ด๋ณผ ๊ฒƒ์ด๋‹ค

 

๋จผ์ € ์™„์„ฑํ™”๋ฉด๋ถ€ํ„ฐ ๋ณด๋„๋ก ํ•˜์ž

 

์ €๊ฒƒ(?)์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ๋จผ์ € ํ•ด์•ผ ํ•  ๊ฒƒ์€

AppBar ๋งŒ๋“ค๊ธฐ!๊ฐ€ ์•„๋‹ˆ๊ณ  lazy column(recyclerView)์— ๋“ค์–ด๊ฐˆ ์•„์ดํ…œ(card)๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๋„๋ก ํ•˜์ž.

 

 

1. item(card) ๋งŒ๋“ค๊ธฐ

@Composable
fun RecyclerItem(randomUser: RandomUser) {
    val typography = MaterialTheme.typography

    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(10.dp),
        elevation = 10.dp,
        shape = RoundedCornerShape(12.dp)
    ) {
        Row(
            modifier = Modifier
                .padding(10.dp),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.spacedBy(10.dp)
        ) {
            ProfileImage(source = randomUser.profileImage)  // ํ”„๋กœํ•„ ์ด๋ฏธ์ง€๋ฅผ ์„ค์ •ํ•œ๋‹ค.

            Column() {
                Text(text = randomUser.name, style = typography.subtitle1)
                Text(text = randomUser.description, style = typography.body1)
            }
        }

    }
}

ํ•˜๋‚˜ํ•˜๋‚˜(?) ์„ค๋ช…ํ•ด ์ฃผ๊ฒ ๋‹ค

 

  • elevation: Card ํ…Œ๋‘๋ฆฌ์— ๊ทธ๋ฆผ์ž(?)ํšจ๊ณผ๋ฅผ ์ค€๋‹ค(ํ…Œ๋‘๋ฆฌ๊ฐ€ ์„ ๋ช…ํžˆ ๋ณด์—ฌ์š”).
  • shape: Card์˜ ๋ชจ์–‘์„ ๋‚˜ํƒ€๋‚ธ๋‹ค
    ์˜ˆ) RoundedCornerShape(ํ…Œ๋‘๋ฆฌ๋ฅผ ๋‘ฅ๊ธ€๊ฒŒ), CircleShape(์›ํ˜•)
  • verticalAlignment: Row์˜ ํ•˜์œ„ ๋ทฐ๋“ค์„ ์ˆ˜์ง ์ •๋ ฌํ•œ๋‹ค
  • horizontalArrangement: ์•„์ดํ…œ ๊ฐ„์˜ ์ˆ˜ํ‰ ๋„ˆ๋น„๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.

์˜ˆ์‹œ(?)

 

2. ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์„ค์ •ํ•˜๊ธฐ

@Composable
fun ProfileImage(source: String, modifier: Modifier = Modifier) {
    // image bitmap
    val bitmap: MutableState<Bitmap?> = remember { mutableStateOf(null) }
    val imageModifier: Modifier = modifier
        .size(50.dp, 50.dp)
        .clip(CircleShape)

    Glide.with(LocalContext.current)
        .asBitmap()
        .load(source)
        .into(object : CustomTarget<Bitmap>() {
            override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
                bitmap.value = resource
            }

            override fun onLoadCleared(placeholder: Drawable?) {}
        })

    // bitmap ์ด ์žˆ์œผ๋ฉด
    bitmap.value?.asImageBitmap()?.let { fetchedBitmap ->
        Image(
            bitmap = fetchedBitmap,
            contentDescription = null,
            contentScale = ContentScale.Fit,
            modifier = imageModifier
        )
    } ?: Image(
        painter = painterResource(id = R.drawable.ic_empty_user),
        contentDescription = null,
        contentScale = ContentScale.Fit,
        modifier = imageModifier
    )
}

์ด๋ฒˆ์—๋„ ํ•˜๋‚˜ํ•˜๋‚˜(?) ์„ค๋ช…ํ•˜์ž๋ฉด

  • clip: ์ด๋ฏธ์ง€์˜ ๋ชจ์–‘์„ ์žก์•„์ค€๋‹ค(RoundedCornerShape, CircleShape)
  • onResourceReady: ์ด๋ฏธ์ง€๊ฐ€ ์ค€๋น„๋˜์—ˆ์„๋•Œ ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์„œ๋“œ
// bitmap ์ด ์žˆ์œผ๋ฉด
bitmap.value?.asImageBitmap()?.let { fetchedBitmap ->
    Image(
        bitmap = fetchedBitmap,
        contentDescription = null,
        contentScale = ContentScale.Fit,
        modifier = imageModifier
    )
} ?: Image(
    painter = painterResource(id = R.drawable.ic_empty_user),
    contentDescription = null,
    contentScale = ContentScale.Fit,
    modifier = imageModifier
)

์ด ๋ถ€๋ถ„์€ ๋น„ํŠธ๋งต์œผ๋กœ ์„ฑ๊ณต์ ์œผ๋กœ ๋ณ€ํ™˜๋˜์—ˆ์„๋•Œ ์œ„์˜ ์ฝ”๋“œ๊ฐ€ ์ˆ˜ํ–‰๋˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์•„๋ž˜ ์ฝ”๋“œ๊ฐ€ ์ˆ˜ํ–‰๋œ๋‹ค.

 

3. toolbar

๋งˆ์ง€๋ง‰์œผ๋กœ toolbar๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ๊ฐ„๋‹จํžˆ ์•Œ์•„๋ณด์ž.

@Composable
fun MyApPBar() {
    TopAppBar(
        elevation = 10.dp,
        backgroundColor = MaterialTheme.colors.primary,
        modifier = Modifier.height(58.dp)
    ) {
        Text(
            text = "๋ฆฌ์ŠคํŠธ",
            modifier = Modifier
                .padding(8.dp)
                .align(Alignment.CenterVertically),
            fontSize = 18.sp,
            fontWeight = FontWeight.Black
        )
    }
}

topAppBar์•ˆ์— Text๋ฅผ ๋„ฃ์–ด์„œ AppBar์˜ title์„ ์„ค์ • ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 


์ •๋ฆฌ

์ด๋ฒˆ์— ๊ณต๋ถ€ํ•ด๋ณด๋ฉด์„œ compose์— glide๋ฅผ ์ฒ˜์Œ ์‚ฌ์šฉํ•ด๋ดค๋‹ค.

์ด๋ฒˆ ๊ณต๋ถ€๋กœ compose์˜ ์žฅ์ ์„ ๋” ์‰ฝ๊ฒŒ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค(์›๋ž˜๋Š” ๋‘ฅ๊ทผ ์ด๋ฏธ์ง€ ์“ฐ๋ ค๋ฉด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€ํ•ด์„œ ์จ์•ผ ํ–ˆ์ง€๋งŒ, ์•ˆ๊ทธ๋ž˜๋„ ๋œ๋‹ค๋Š”๊ฒƒ์ด ์ข‹์•˜๋‹ค.๊ฐœ๊ฟ€)

728x90