ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Compose 학습 - 1 : 기초
    안드로이드 학습/Compose 2025. 2. 5. 17:18

    링크 : https://developer.android.com/courses/pathways/compose?hl=ko

     

    Jetpack Compose  |  Android Developers

    네이티브 Android UI를 빌드하기 위한 최신 도구 키트인 Compose에 관해 알아봅니다.

    developer.android.com

     

    Compose에서는 함수에 @Compose 주석을 추가해야한다.  

    @Composable
    fun Greeting(name: String, modifier: Modifier = Modifier) {
        Text(
            text = "Hello $name!",
            modifier = modifier
        )
    }

     

    중간중간 따라 쓰는게 귀찮아서 완료된 코드로 분석

    1. onCreate 부분

    class PracticeActivity2 : ComponentActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            enableEdgeToEdge()
            setContent {
                BasicsCodelabTheme {
                    MyApp2(modifier = Modifier.fillMaxSize())
                }
            }
        }
    }

     

    Activity에서 onCreate로 시작하는 부분이 Compose에서는 이렇게 시작된다. 

     

    1. ComponentActivity는 AppCompatActivity보다 더 가볍고 Compose에 더 최적화 되어 있다. 

     

    2. enableEdgeToEdge : 이 기능은 상태바내비게이션 바 영역까지 콘텐츠를 확장할 수 있도록 해줍니다.

     

    3. Compose에서는 xml이 아닌 Composable 함수로 UI를 구성할 수 있다. 

     

    4. BasicsCodelabTheme에서 기본 색상, 폰트 스타일 등을 관리한다. 

     

    5. modifier의 fillMaxSize로 화면을 가득 채우도록 지정한다. 

     

    2. MyApp2 부분

    @Composable
    fun MyApp2(
        modifier: Modifier = Modifier
    ) {
        var shouldShowOnboarding by rememberSaveable { mutableStateOf(true) } // by remember
    
        Surface(modifier) {
            if (shouldShowOnboarding) {
                OnboardingScreen(onContinueClicked = { shouldShowOnboarding = false })
            } else {
                Greetings()
            }
        }
    }

     

    1. 외부에서 Modifier를 전달받으면 그것을 사용하고 그렇지 않다면 기본 Modifier를 사용한다. 

     

    2. Compose에서 변수를 저장하는 방법은 rememberSaveable을 사용해서 저장한다. 

    by 키워드를 사용해서 shouldShowOnboarding.value 대신 바로 직접 접근할 수 있게 해준다. 

     var shouldShowOnboarding by rememberSaveable { mutableStateOf(true) } // by remember

     

    3. OnboardingScreen 함수에는 onContinueClicked를 전달하는데 이게 호출되면 shouldShowOnboarding이 false가 된다. 

     

    3. OnboardingScreen()

    @Composable
    fun OnboardingScreen(
        onContinueClicked: () -> Unit,
        modifier: Modifier = Modifier
    ) {
    
        Column(
            modifier = modifier.fillMaxSize(),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text("Welcome to the Basics Codelab!")
            Button(
                modifier = Modifier.padding(vertical = 24.dp),
                onClick = onContinueClicked
            ) {
                Text("Continue")
            }
        }
    }
    

     

    1. onContinueClicked은 앞서 보았든 shouldShowOnboarding를 false로 바꿔주는 함수고 이것을 전달 받아 사용한다. 

     

    2. Column은 LinearLayout에서 Horizontal 과 비슷하게 각 Composable 함수를 세로로 나열해준다. 

     

    3. Text : TextView

     

    4. Button : Button 이고 onClick으로 수행할 기능을 전달받은 onContinueClicked이다. MyApp2의 shouldShowOnboarding을 false로 바꾸고 화면을 변경한다. 

    Modifier.padding(vertical = 24.dp)는 위아래로 24dp 만큼의 여백을 제공한다. 

    Button 내부의 Text는 버튼의 글자다.

     

    4. Greetings()

    @Composable
    private fun Greetings(
        modifier: Modifier = Modifier,
        names: List<String> = List(1000) { "$it" }
    ) {
        LazyColumn(modifier = modifier.padding(vertical = 4.dp)) {
            items(items = names) { name ->
                CustomGreeting(name = name)
            }
        }
    }

     

    1. List를 외부에서 받거나 생성한다. 0부터 999까지 List로 채워진다. 

    names: List<String> = List(1000) { "$it" }

     

    2. LazyColumn은 RecyclerView와 같은 역할을 한다. padding의 4dp는 가장 위와 가장 아래에 4dp 만큼 간격을 준다. 

     LazyColumn(modifier = modifier.padding(vertical = 4.dp))

     

    3. items 는 List의 각 항목을 name으로 받아서 UI를 만듦.

    items(items = names) → names

     

    5. CustomGreeting()

    @Composable
    fun CustomGreeting(name: String, modifier: Modifier = Modifier) {
    
        var expanded by rememberSaveable { mutableStateOf(false) }
    
        val extraPadding by animateDpAsState(
            if (expanded) 48.dp else 0.dp,
            animationSpec = spring(
                dampingRatio = Spring.DampingRatioMediumBouncy,
                stiffness = Spring.StiffnessLow
            )
        )
    
        Surface(
            color = MaterialTheme.colorScheme.primary,
            modifier = modifier.padding(
                vertical = 4.dp,
                horizontal = 8.dp
            ) // 이부분은 각 Surface 별로 margin 주는 것과 같다
        ) {
            Row(modifier = Modifier.padding(24.dp)) {
                Column(
                    modifier = Modifier
                        .weight(1f)
                        .padding(bottom = extraPadding.coerceAtLeast(0.dp))
                ) {
                    Text(text = "Hello, ")
                    Text(
                        text = name, style = MaterialTheme.typography.headlineMedium.copy(
                            fontWeight = FontWeight.ExtraBold
                        )
                    )
                }
                ElevatedButton(
                    onClick = { expanded = !expanded }
                ) {
                    Text(if (expanded) "Show less" else "Show more")
                }
            }
        }
    }

     

    1. Greetings에서 정의된 LazyColumn에 각 item 별로 CustomGreeting의 UI를 보여준다. 

     

    2. item의 배경은 지정된 MaterialTheme의 primary 색상으로 지정. padding은 각 item 사이의 간격이 좌우 4dp, 위아래 8dp으로 지정.

        Surface(
            color = MaterialTheme.colorScheme.primary,
            modifier = modifier.padding(
                vertical = 4.dp,
                horizontal = 8.dp
            ) // 이부분은 각 Surface 별로 margin 주는 것과 같다
        )

     

    3. weight을 사용해서 Row내에 남은 공간을 가능한 많이 차지하도록 한다. 

    Column(
        modifier = Modifier
            .weight(1f)
            .padding(bottom = extraPadding.coerceAtLeast(0.dp))
    )

     

     extraPadding.coerceAtLeast(0.dp) 이 0보다 작아져도 0으로 변환된다. 

     

    4. extrapaddig은 아래의 animationSpec이 0보다 작게 만든다. 그래서 padding에서 coerceAtLeast(0.dp)를 사용한다. 

     

    val extraPadding by animateDpAsState(
        if (expanded) 48.dp else 0.dp,
        animationSpec = spring(
            dampingRatio = Spring.DampingRatioMediumBouncy,
            stiffness = Spring.StiffnessLow
        )
    )
    

     

     

Designed by Tistory.