Primary/Compose

[Relay] Compose Theme에 접근하는 방법

해스끼 2022. 11. 28. 17:14

아직 Experimental feature이긴 하지만, Relay에서 Compose theme에 접근할 수 있는 방법이 있다. Figma에서 사용하는 디자인 값을 Compose의 값으로 매핑하면 된다.

구체적인 과정은 다음과 같다.

  1. Figma의 스타일 값을 json으로 변환한다.
  2. Json 스타일 값을 Compose theme 값으로 변환한다.
  3. 완료!

세팅

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이긴 하지만 필요한 기능은 모두 갖췄다. 좋은데? 나중에 유용하게 사용할 수 있을 것 같다.