안드로이드 앱 개발 공부/jetpack Compose

JetPack Compose_Image, Card, 상태

플래시🦥 2023. 1. 4.
반응형

card 안에 box 를 넣어주고 그 안에 이미지를 추가하려 한다. 

 

setContent {
    ImageCard()
}
@Composable
fun ImageCard(){
    Card(
        modifier= Modifier
            .fillMaxWidth(0.5f)   //fraction : 비율
            .padding(16.dp),
        shape = RoundedCornerShape(8.dp), //모서리 둥글게
        elevation = 5.dp
    ){
        Box (
            modifier= Modifier.height(100.dp)
            ){
            Image(
                painter = painterResource(id = R.drawable.emergency),
                contentDescription = "poster",  //필수
                contentScale = ContentScale.Crop
            )
        }
    }
}

card의 modifer에 있는 .fillMaxWidth(0.5f)는 width를 꽉채워 표시하라는 설정에 비율을 넣어준 것이다. 

그래서 width 에서 0.5f 즉, 전체의 절반 비율로 꽉차게 설정한 것이다. 

shape = RoundedCornerShape(8.dp) 는 카드의 모서리를 둥글게 설정한 것이고, elevation은 elevation기능이다. 

 

Image를 가져오는 것에 여러 방법이 있지만 그중 drawable 파일을 가져다 쓸 것이기 때문에 Painter를 사용한다. 

contentDexriprion은 필수이고, contentScale = ContentScale.Crop를 추가하여 이미지를 크롭하여 크기조정한다.

 

 

결과

 

이 이미지 안에 하트 아이콘을 넣어주려고 한다.

Box (
    modifier= Modifier.fillMaxSize(),
    contentAlignment = Alignment.TopEnd //오른쪽 위에
){
    IconButton(onClick = {}) {
        Icon(
            imageVector = Icons.Default.FavoriteBorder,
            contentDescription ="Favorite",
            tint = Color.White
        )

    }
}

이 코드를 이미지 바로 아래에 넣어 주면 된다.

그래서 상위 Box의 크기에 fillMaxSize하고, Alignment.TopEnd 하여 

이렇게 표시가 된다. 

 

그다음은 아이콘을 클릭했을 때 변화가 있게끔 수정해 보자.

 

//상태 기억 필요
val isFavorite = remember { //var isFavorite: MutableState<Boolean>
    mutableStateOf(false)
}   //변경되면 ui가 다시 그려짐

이것을 추가하여 상태를 기억할 수 있는 상수를 선언을 해주고, 

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

}

이렇게 수정해주면 된다.

onClick에 클릭했을 때 마다 isFavorite의 value가 반대의 값이 들어가도록 해주고 

imageVector를 넣어줄 때 상태를 기억하고 있는 상수 isFavorite가 true일때와 false일때 아이콘의 종류를 달리 할 수 있도록 해주면 된다.

 

 

그리고 매번 값을 가져올 때 .value를 써주는 것이 번거로우니

import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue

이걸 import 해주고 

var isFavorite by remember { //var isFavorite: Boolean
    mutableStateOf(false)
}

=를 by로 수정하면 된다. 

그리고 변수의 형태가 MutableState<Boolean> 가 아닌 Boolean로 변하였기 때문에 val 이 아닌 var 로 선언해 주어야 한다. 

 

상태보존을 위해서 remeber 대신 rememberSaveable를 사용하면 핸드폰을 기울일 때 상태가 보존이 된다고 하는데,

remember로 사용해도 상태가 유지가 되니 이 부분을 좀 더 알아볼 필요가 있다.

 

지금까지의  코드는 아래와 같다. 

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ImageCard()
        }
    }
}

@Composable
fun ImageCard(){
    //상태 기억 필요
    var isFavorite by rememberSaveable { //var isFavorite: MutableState<Boolean>
        mutableStateOf(false)
    }   //변경되면 ui가 다시 그려짐

    Card(
        modifier= Modifier
            .fillMaxWidth(0.5f)   //fraction : 비율
            .padding(16.dp),
        shape = RoundedCornerShape(8.dp), //모서리 둥글게
        elevation = 5.dp
    ){
        Box (
            modifier= Modifier.height(100.dp)
            ){
            Image(
                painter = painterResource(id = R.drawable.emergency),
                contentDescription = "poster",  //필수
                contentScale = ContentScale.Crop
            )
            Box (
                modifier= Modifier.fillMaxSize(),
                contentAlignment = Alignment.TopEnd //오른쪽 위에
            ){
                IconButton(onClick = {
                    isFavorite=!isFavorite
                }) {
                    Icon(
                        imageVector = if(isFavorite) Icons.Default.Favorite else Icons.Default.FavoriteBorder,
                        contentDescription ="Favorite",
                        tint = Color.White
                    )

                }
            }
        }

    }
}

그런데 이렇게 하면 ImageCard()가  값을 유지하고 있기 때문에 재사용될 수 없다. 

그래서 밖에서 값을 주는 방법으로 수정을 해야한다. 

 

그리고  상태 뿐만 아니라 modifier로 외부에서 지정해 주면 좋다. 

setContent {
    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(100.dp)
            ){
            Image(
                painter = painterResource(id = R.drawable.emergency),
                contentDescription = "poster",  //필수
                contentScale = ContentScale.Crop
            )
            Box (
                modifier= Modifier.fillMaxSize(),
                contentAlignment = Alignment.TopEnd //오른쪽 위에
            ){
                IconButton(onClick = {
                    onTabFavorite(!isFavorite)  //onTabFavorite.invoke(!isFavorite) 인데 invoke는 생략아 가능
                }) {
                    Icon(
                        imageVector = if(isFavorite) Icons.Default.Favorite else Icons.Default.FavoriteBorder,
                        contentDescription ="Favorite",
                        tint = Color.White
                    )

                }
            }
        }

    }
}

ImageCard() 함수에 매개변수로 넣어주고 호출 할 때마다 원하는 방식으로 표시되게끔 해줄 수 있다. 

 

최종 : 하트 아이콘 클릭 전 / 후

 

728x90
반응형

댓글