본문 바로가기

Jetpack Compose

[Jetpack Compose] 6. State

아래 영상을 보고 정리한 게시글입니다.

https://www.youtube.com/watch?v=dAwnZfZPP48&list=PLxTmPHxRH3VV8lJq8WSlBAhmV52O2Lu7n&index=5 


IconButton을 클릴할 때마다 동작을 부여하고 싶음

(=> 클릭할 때마다 하트가 차거나 비거나 번갈아 나오도록 할 예정)


State

Compose는 State 기반으로 동작한다

 

원래는 boolean 변수 만들어서 값을 바꿔줘가면 되지만

jetpack compose는 state를 사용해서 깔끔하게 UI를 그릴 수 있음

state가 변경될 때마다 그에 해당하는 부분만 UI를 새로 그림

val isFavorite = remember {
    mutableStateOf(false)
}
IconButton(onClick = {
    isFavorite.value = !isFavorite.value
}) {
    Icon(
        imageVector = if (isFavorite.value) Icons.Default.Favorite else Icons.Default.FavoriteBorder,
        contentDescription = "favorite",
        tint = Color.White
    )
}

위임

state를 사용하면 위와 같이

값에 접근할 때는 .value로 접근해야 됨

 

by 키워드로 setter, getter를 위임하면 .value를 안 써도 된다

var isFavorite by remember {
    mutableStateOf(false)
}
IconButton(onClick = {
    isFavorite = !isFavorite
}) {
    Icon(
        imageVector = if (isFavorite) Icons.Default.Favorite else Icons.Default.FavoriteBorder,
        contentDescription = "favorite",
        tint = Color.White
    )
}

rememberSaveable

화면 회전했을 때 변수가 초기화가 됨

=> 채워진 하트가 빈 하트가 됨

 

rememverSaveable을 사용하면 간단하게 사용 가능

var isFavorite by rememberSaveable {
    mutableStateOf(false)
}

재사용 가능하기 쉽게 바꾸기

composable function은 재사용 가능하기 쉽게 하려고 만든 것임

 

아래 조건을 만족하면 좋음

  • 외부에서 modifier를 지정해주는 것이 좋음
  • 변수도 외부에서 지정해주는 것이 좋음
  • callback 함수를 통해서 호출한 곳에서 변수를 바꿔줌
    • 변수를 parameter로 받으면 val 변수가 돼서 수정이 안됨
@Preview(showBackground = true)
@Composable
fun TestView() {
    var isFavorite by rememberSaveable {
        mutableStateOf(false)
    }

    ImageCard(
        modifier = Modifier
            .fillMaxWidth(0.5f)
            .padding(16.dp),
        isFavorite = isFavorite
    ) { favorite ->
        isFavorite = favorite
    }
}
@Composable
fun ImageCard(
    modifier: Modifier = Modifier,
    isFavorite: Boolean,
    onTabFavorite: (Boolean) -> Unit,
) {
    Card(
        modifier = modifier,
        shape = RoundedCornerShape(8.dp),
        elevation = 5.dp
    ) {
        Box(
            modifier = Modifier
                .height(200.dp)
        ) {
            Image(
                painter = painterResource(id = R.drawable.profile),
                contentDescription = "poster",
                contentScale = ContentScale.Crop
            )
            Box(
                modifier = Modifier
                    .fillMaxSize(),
                contentAlignment = Alignment.TopEnd
            ) {
                IconButton(onClick = {
                    onTabFavorite(!isFavorite)
                }) {
                    Icon(
                        imageVector = if (isFavorite) Icons.Default.Favorite else Icons.Default.FavoriteBorder,
                        contentDescription = "favorite",
                        tint = Color.Red
                    )
                }
            }
        }
    }
}

결과물