이번 과정에서는 이미 알고있는 것들을 적용하고 몇가지 힌트와 함께 새로운 개념을 배우것이다.

이 화면을 만들어 보자.

버튼을 아이콘으로 교체하기

  • 하위 Icon과 IconButton 컴포저블을 함께 사용한다.
  • 아이콘 리소스는 material-icons-extended 아티팩트에서 사용가능한 Icons.Filled.ExpandLess 및 Icons.Filled.ExpandMore를 사용한다. 다음의 코드라인을 app/build.gradle 파일의 의존성으로 추가한다.
implementation "androidx.compose.material:material-icons-extended:$compose_version"
  • padding을 수정하여 정렬한다.
  • 접근성을 위해 content description을 추가하자.

문자열 리소스 사용하기

“Show more” 및 “Show less” 에 대한 content description을 나타내고, 이를 if 문을 사용하여 간단히 추가하자.

contentDescription = if (expanded) "Show less" else "Show more"

하지만 하드코딩된 문자열은 좋지 못한 방법이고 strings.xml 파일로부터 가져오는 것이 좋다.

각 문자열에 대해 Extract string resource를 사용하자. 안드로이드 스튜디오에 있는 Context Actions에서 이런 작업을 자동으로 할 수 있다.

대안으로는 app/src/res/values/strings.xml 을 열고 다음의 라인을 추가하는 것이다.

<string name="show_less">Show less</string>
<string name="show_more">Show more</string>

더 보기 나타내기

각 카드 사이즈에 맞게 변경되도록 “Composem ipsum” 텍스트는 나타나거나 사라진다.

  • 새로운 Text 컴포저블을 Column에 Greeting으로 추가하고 아이템이 확장될 때 보여줄 수 있도록 한다.
  • extraPadding은 제거하고 대신에 animateContentSize를 Row에 추가한다. 이를 통해 수동으로 조작하기 어려운 애니메이션을 생성 작업을 자동화 한다. 또한, 이는 coerceAtLeast함수를 제거할 수 있도록 한다.

elevation 및 shapes

  • shadow와 clip을 함께 사용하여 카드 처럼 보이게 만들 수 있다. 하지만 머테리얼 컴포저블에 포함된 Card라는 것이 존재한다.

최종 코드는 다음과 같다.

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

@Composable
private fun MyApp() {
    var shouldShowOnboarding by rememberSaveable { mutableStateOf(true) }

    if (shouldShowOnboarding) {
        OnboardingScreen(onContinueClicked = { shouldShowOnboarding = false })
    } else {
        Greetings()
    }
}

@Composable
private fun OnboardingScreen(onContinueClicked: () -> Unit) {
    Surface {
        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")
            }
        }
    }
}

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

@Composable
private fun Greeting(name: String) {
    Card(
        backgroundColor = MaterialTheme.colors.primary,
        modifier = Modifier.padding(vertical = 4.dp, horizontal = 8.dp)
    ) {
        CardContent(name)
    }
}

@Composable
private fun CardContent(name: String) {
    var expanded by remember { mutableStateOf(false) }
   
    Row(
        modifier = Modifier
            .padding(12.dp)
            .animateContentSize(
                animationSpec = spring(
                    dampingRatio = Spring.DampingRatioMediumBouncy,
                    stiffness = Spring.StiffnessLow
                )
            )
    ) {
        Column(
            modifier = Modifier
                .weight(1f)
                .padding(12.dp)
        ) {
            Text(text = "Hello, ")
            Text(
                text = name,
                style = MaterialTheme.typography.h4.copy(
                    fontWeight = FontWeight.ExtraBold
                )
            )
            if (expanded) {
                Text(
                    text = ("Composem ipsum color sit lazy, " +
                        "padding theme elit, sed do bouncy. ").repeat(4),
                )
            }
        }
        IconButton(onClick = { expanded = !expanded }) {
            Icon(
                imageVector = if (expanded) Filled.ExpandLess else Filled.ExpandMore,
                contentDescription = if (expanded) {
                    stringResource(R.string.show_less)
                } else {
                    stringResource(R.string.show_more)
                }

            )
        }
    }
}

@Preview(
    showBackground = true,
    widthDp = 320,
    uiMode = UI_MODE_NIGHT_YES,
    name = "DefaultPreviewDark"
)
@Preview(showBackground = true, widthDp = 320)
@Composable
fun DefaultPreview() {
    BasicsCodelabTheme {
        Greetings()
    }
}

@Preview(showBackground = true, widthDp = 320, heightDp = 320)
@Composable
fun OnboardingPreview() {
    BasicsCodelabTheme {
        OnboardingScreen(onContinueClicked = {})
    }
}

후원하기

카테고리: Compose

0개의 댓글

답글 남기기

Avatar placeholder

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.