[Relay] Compose Theme에 접근하는 방법
아직 Experimental feature이긴 하지만, Relay에서 Compose theme에 접근할 수 있는 방법이 있다. Figma에서 사용하는 디자인 값을 Compose의 값으로 매핑하면 된다.
구체적인 과정은 다음과 같다.
- Figma의 스타일 값을 json으로 변환한다.
- Json 스타일 값을 Compose theme 값으로 변환한다.
- 완료!
세팅
Theme mapping을 사용하려면 UI package를 가져올 때 하단 옵션을 활성화해야 한다.
Material3, Material(2), 커스텀 테마를 지원한다. 커스텀 테마를 사용하려면 위에서 본 mapping 파일을 직접 만들어야 한다. 이 글에서는 Material 테마를 사용해 보겠다.
App theme에 앱에서 사용되는 Theme 클래스의 패키지명을 적으면 프리뷰에 해당 테마가 적용된다. ``RelayTestTheme``의 패키지명을 입력하면 이렇게 된다.
// generated code by Relay
@Preview(widthDp = 79, heightDp = 29)
@Composable
private fun SampleButtonPreview() {
// 테마를 지정하지 않을 경우
// MaterialTheme를 사용
RelayTestTheme {
SampleButton(text = "sample")
}
}
색깔
Figma에서 Material color theme에 접근하는 포맷은 다음과 같다.
``M3/sys/[light/dark]/[colorName]``
``colorName``이 camelCase로 표현된 경우에는 대문자 앞에 ``-``를 넣고, 대문자를 소문자로 바꿔야 한다. 예를 들어 ``onPrimary``는 ``M3/sys/light/on-primary``로 표현된다. 모든 매핑 정보는 ``app/src/main/ui-package-resources/style-mappings/m3_design_kit.json`` 파일에서 확인할 수 있다.
실제로 색깔이 잘 변환되는지 검사해 보자. Figma에서 사각형 3개를 둘러싸는 큰 사각형을 그려 보았다. 색이 제대로 변환되는지 확인하기 위해 일부러 아무 색이나 채웠다.
앱에서 사용한 색은 다음과 같다.
private val LightColorScheme = lightColorScheme(
primary = Purple80,
secondary = PurpleGrey80,
tertiary = Pink80,
background = Color.White,
)
어디 확인해 볼까?
제대로 나온다! 실제로 생성된 코드에서 ``MaterialTheme.colorScheme``에 접근하고 있기 때문이다.
// generated code by Relay
@Composable
fun First(
modifier: Modifier = Modifier,
content: @Composable RelayContainerScope.() -> Unit
) {
RelayContainer(
backgroundColor = MaterialTheme.colorScheme.primary,
isStructured = false,
content = content,
modifier = modifier.requiredWidth(37.0.dp).requiredHeight(18.0.dp)
)
}
참고: 색깔이 제대로 보이지 않는다면 테마를 적용할 때 ``dynamicColor``를 ``false``로 설정했는지 확인하자. 안 그러면 다른 색깔이 보인다.
RelayTestTheme(dynamicColor = false) {
// ...
}
글꼴
글꼴 역시 같은 방법으로 접근할 수 있다. 텍스트 스타일 이름을 다음과 같이 지으면 된다.
``M3/[type]/[size]``
예를 들어 ``MaterialTheme.typography.bodyLarge``을 적용하고 싶다면 스타일 이름을 ``M3/body/large``로 하면 된다.
글꼴이 제대로 적용되는지 확인해 보자. 샘플 버튼에 ``bodyMedium`` 폰트를 적용해 보았다.
눈으로는 판별하기 힘들지만, 생성된 코드에서 ``MaterialTheme.typography.bodyMedium``에 접근하고 있기 때문에 올바르게 구현했다고 할 수 있다.
// generated code by Relay
@Composable
fun Sample(
text: String,
modifier: Modifier = Modifier
) {
RelayText(
content = text,
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
fontFamily = MaterialTheme.typography.bodyMedium.fontFamily,
color = Color(
alpha = 255,
red = 0,
green = 0,
blue = 0
),
height = MaterialTheme.typography.bodyMedium.lineHeight,
letterSpacing = MaterialTheme.typography.bodyMedium.letterSpacing,
textAlign = TextAlign.Left,
fontWeight = MaterialTheme.typography.bodyMedium.fontWeight,
modifier = modifier
)
}
그나저나 코드 한번 참 복잡하네..
정리
Experimental이긴 하지만 필요한 기능은 모두 갖췄다. 좋은데? 나중에 유용하게 사용할 수 있을 것 같다.