📱 안드로이드 Android ~ Kotlin

[Android/Kotlin] Compose State 상태, 기본 레이아웃 사용하기(Box, Card, Image, IconButton, Icon)

핑크빛연어 2023. 6. 21. 11:17

 

Android Jetpack Compose 사용 시 알아야 할 state 상태와 기본 레이아웃‼️

 

 

🚨 State - 앱의 상태

Android Compose 는 현재 상태에 따라 Composable 를 구성하여 사용자에게 보여질 화면을 구성한다.

만약 상태(state) 가 변화게 되면 재구성(Re-Compose) 를 통해 화면을 업데이트한다.

 

Composable 은 상태를 가지는 여부에 따라 두가지 타입으로 나뉜다.

✔️ 상태를 가지고 있는 Stateful Composable

✔️ 상태를 가자지 않는 Stateless Composable

 

- Stateful Composable 은 state 가 바뀌면 자기 자신과 자식의 Composable 을 재구성(ReComposition) 하게 된다.

- Stateless Composable 은 상태가 없기 때문에 스스로 재구성을 할수 없으며 부모의 Composable 이 재구성되어야 자신을 재구성을 할 수 있게 된다.

 

이전 state 를 기억해야 하는 경우 remember 를 이용해 값을 저장할 수 있다

 

state 저장 및 변경 시 MutableState 객체를 사용하며 MutableState 생성을 위해 mutableStateOf api 가 사용된다.

 

MutableState 객체 선언 방법

  • val mutableState = remember { mutableStateOf(default) }
  • var value by remember { mutableStateOf(default) }
  • val (value, setValue) = remember { mutableStateOf(default) }
setContent {

    Box(
        modifier = Modifier
            .fillMaxWidth()
            .fillMaxHeight(),
    ) {

        // *** 1. val mutableState = remember { mutableStateOf(default) }
        val txtState1 = remember {mutableStateOf("")}
        TextField(
            value = txtState1.value,
            onValueChange = { txtValue -> txtState1.value = txtValue }
        )


        // *** 2. var value by remember { mutableStateOf(default) }
        var txtState2 by remember {mutableStateOf("")}
        TextField(
            value = txtState2,
            onValueChange = { txtValue -> txtState2 = txtValue }
        )


        // *** 3. val (value, setValue) = remember { mutableStateOf(default) }
        val (txtState3, setTxtState) = remember {mutableStateOf("")}
        TextField(
            value = txtState3,
            onValueChange = setTxtState
        )

    }
}

 

 

State remeber 를 사용한 TextField

 

 

https://developer.android.com/jetpack/compose/state?hl=ko 

 

상태 및 Jetpack Compose  |  Android Developers

상태 및 Jetpack Compose 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 앱의 상태는 시간이 지남에 따라 변할 수 있는 값을 의미합니다. 이는 매우 광범위한 정

developer.android.com

 

 

 

🚨 State + 기본 레이아웃 사용하기(Box, Card, Image, IconButton, Icon)

 

기본 레이아웃 사용하기

 

✔️ Box 레이아웃 

  • FrameLayout 과 비슷
  • 레이아웃을 겹쳐서 사용 가능
    • fillMaxWeight : 가로길이가 꽉차게
    • fillMaxHeight : 세로길이가 꽉차게
    • fillMaxSize : 가로세로 다 꽉차게
    • align : Box 내부 Child 위치를 지정 (Alignment.TopStart, Alignment.TopCenter, Alignment.BottomEnd, ...)

✔️ Card 레이아웃

  • CardView 와 비슷
  • roundShape(모서리 둥글게), elevation(그림자) 설정 가능

 

✔️ Image 레이아웃

  • ImageView 와 비슷
  • 이미지 리소스, scale 설정 가능

 

✔️ IconButton 레이아웃

  • onClick 이벤트 설정 가능

 

✔️ Icon 레이아웃

  • 이미지 리소스, tint 설정 가능

 

✍🏻 state 상태기본 레이아웃들을 사용하여 

곰돌이 이미지와 하트 아이콘을 Box 로 겹쳐서 위치하도록 하고,

비어있는 하트 아이콘을 클릭하면 하트색상 활성화되게 (♡ → ♥︎), 

색상이 있는 하트 아이콘을 클릭하면 비어있는 하트로 되도록 (♥︎ → ♡)

구현하였습니다.

 

 

결과 화면

  ♥︎ & ♥︎  

 

 

Activity 소스코드 (BasicLayoutActivity.kt)

class BasicLayoutActivity: ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {

            var isFavCard by rememberSaveable {  // isFavCard 는 Boolean 값이다 remeberSaveable : 화면 회전시에도 상태 저장
                mutableStateOf(false)
            }

            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .fillMaxHeight(),
            ) {

                CardFavorite(  // ImageCard 함수 사용
                    mCardModifier = Modifier
                        .height(250.dp)
                        .fillMaxWidth(0.7f)
                        .padding(10.dp)
                        .align(Alignment.Center),  //Box 내부 Child 위치를 지정 - Center
                    mBoxModifier = Modifier
                        .background(colorResource(id = R.color.teal_200))
                        .padding(10.dp),
                    mPainter = painterResource(id = R.drawable.img_mint),
                    mIsFavCard = isFavCard
                ) { paramFavCard ->
                    isFavCard = paramFavCard
                }

            }
        }
    }

}


/**
 * ImageCard 컴포저블 함수
 *
 * @param mCardModifier     Card 레이아웃의 modifier
 * @param mBoxModifier     Box 레이아웃의 modifier
 * @param mPainter     Image 레이아웃의 painter
 * @param mIsFavCard     IconButton 레이아웃의 색상 활성화 여부
 * @param onTabFavCard     IconButton 레이아웃의 onClick 콜백
 */
@Composable
fun CardFavorite(
    mCardModifier: Modifier,
    mBoxModifier: Modifier,
    mPainter: Painter,
    mIsFavCard: Boolean,
    onTabFavCard: (Boolean) -> Unit
) {

    /**
     * Card 레이아웃
     *   - CareView 와 비슷
     */
    Card(
        modifier = mCardModifier,
        shape = RoundedCornerShape(8.dp),
        elevation = 5.dp,
    ) {

        /**
         * Box 레이아웃
         *   - FrameLayout 과 비슷
         *   - 레이아웃을 겹쳐서 사용 가능
         */
        Box(
            modifier = mBoxModifier,
        ) {

            /**
             * Image 레이아웃
             */
            Image(
                painter = mPainter,
                contentDescription = "poster",
                contentScale = ContentScale.Crop
            )
            Box(
                modifier = Modifier
                    .fillMaxSize(),
                contentAlignment = Alignment.TopEnd
            ) {

                /**
                 * IconButton 레이아웃
                 */
                IconButton(onClick = {
                        onTabFavCard(!mIsFavCard)
                    }
                ) {

                    /**
                     * Icon 레이아웃
                     */
                    Icon(
                        imageVector = if(mIsFavCard) Icons.Default.Favorite else Icons.Default.FavoriteBorder,
                        contentDescription = "favorite card btn",
                        tint = Color.Red
                    )
                }
            }
        }
    }

}


@Preview(showBackground = true)
@Composable
fun BasicLayoutPreview() {

    var isFavCard  = true

    Box(
        modifier = Modifier
            .fillMaxWidth()  // 가로길이 꽉차게
            .fillMaxHeight()  // 세로길이 꽉차게
            .fillMaxSize(),  // 가로세로 꽉차게
    ) {

        CardFavorite(  // ImageCard 함수 사용
            mCardModifier = Modifier
                .height(250.dp)
                .fillMaxWidth(0.7f)
                .padding(10.dp)
                .align(Alignment.Center),  //Box 내부 Child 위치를 지정 - Center
            mBoxModifier = Modifier
                .background(colorResource(id = R.color.teal_200))
                .padding(10.dp),
            mPainter = painterResource(id = R.drawable.img_mint),
            mIsFavCard = isFavCard
        ) { paramFavCard ->
            isFavCard = paramFavCard
        }

    }
}

 

 

감사합니다 :)

728x90
반응형