Android Design
Google이 Material 3 Expressive를 사용하여 Android 앱을 디자인하는 방법을 결정과 Compose 코드로 번역합니다. Expressive는 별도의 디자인 언어가 아니라, Google이 '확장팩'이라고 부르는 Material 3에 옵트인 API, 컴포넌트, 디자인 전술을 더한 것입니다. 여기의 가이드라인, 연구, API 이름은 m3.material.io, Android 디자인 가이드(developer.android.com/design/ui), Wear OS 디자인 가이드, Google I/O 및 Android Developers 발표, 그리고 androidx 소스에서 가져왔습니다.
핵심 원칙: 화면이 디자인되었다고 느껴지려면 강조가 의도적으로 사용되어야 합니다. 화면의 목적을 순위 매기고, 크기, 색상 대비, 형태, 타이포그래피, 컨테이닝, 모션을 최우선 목표에 가장 많이, 다음 목표에는 덜, 나머지에는 거의 사용하지 않습니다. 기본 Material 코드는 모든 요소에 동등한 가중치를 부여하여 템플릿처럼 보이게 합니다.
(Google) 표시된 인용문과 규칙은 Google의 지침에서 따왔습니다. (기본값) 표시된 규칙은 이 스킬의 시작점입니다: 화면의 방향이 다른 이유를 제시하지 않는 한 따르십시오.
대상 화면. 이 스킬은 휴대폰, 태블릿, 데스크톱, Wear OS 앱 화면을 대상으로 합니다. Wear OS 화면의 경우 먼저 references/wear-os.md를 읽으십시오; 이 파일과 다른 부분에서는 wear-os.md가 우선합니다. 스캐폴딩 및 마이그레이션에는 wear-compose-m3 스킬을 사용하십시오. Wear 타일, 워치 페이스, 홈 화면 위젯은 이 스킬의 범위를 벗어납니다: Wear 위젯과 타일에는 wear-widgets 스킬을, 홈 화면 위젯에는 Glance 스킬을 사용하십시오.
시각적 도구
실제 Compose 코드를 구현하거나 검토하려면 compose-preview CLI와 compose-preview 및 compose-ui-builder 스킬이 필요합니다: compose-preview를 읽고 따르십시오. 이 스킬은 도구 선택, 렌더링, 문제 해결을 담당합니다. UI Builder 디자인 작성 요청의 경우 compose-ui-builder를 따르십시오. 이 스킬은 디자인 결정과 화면 점검을 담당합니다. 종속성을 사용할 수 없으면 보고하고, 도구를 설치하거나 다른 렌더러로 대체하지 말고 이 저장소의 README 설정 섹션을 참조하도록 사용자에게 안내하십시오.
탐색 또는 구현
요청이 새 앱, 새 화면, 또는 리디자인의 디자인과 관련된 경우(폴리싱, 시각적 방향, Material 3 Expressive를 요청하거나 이 스킬을 명명하는 경우), '빌드'라고 말하더라도 제안서로 시작하십시오: android-design-explore 스킬을 따르고, 프리뷰어 앱에서 제안서를 보여준 후, 사용자가 방향을 승인할 때까지 Compose를 작성하지 마십시오. 사용자가 '제안서 건너뛰기', '그냥 코딩해'라고 말하거나 승인된 제안서가 이미 있는 경우 제안서를 건너뛰십시오; 승인된 제안서는 해당 스킬의 '승인 및 포팅' 단계(export_kotlin으로 시작)를 사용하여 포팅하십시오.
디자인을 묻지 않는 일반적인 빌드는 아래의 디자인 결정과 화면 점검을 적용하여 바로 코드로 이동합니다.
기존 디자인 내의 변경(수정, 조정, 검토, 승인된 화면의 새 상태)은 자체 승인 및 브랜치 규칙에 따라 실제 프로젝트로 바로 이동하며, 아래의 디자인 결정과 화면 점검을 사용합니다.
0. UI 작성 전
코드 작성 전에 답변에 다음 질문들을 한두 문장씩 포함하십시오. 이 단계를 건너뛰면 일반적인 화면이 만들어집니다.
- 목표 순위 매기기. 이 화면의 기본 작업은 무엇인가요? 보조 및 3차 작업은 무엇인가요? (Google: "각 페이지에서 하나의 기본 작업으로 단순화")
- 방향 선택하기. 화면의 감정적 특성, 그것을 정의하는 콘텐츠 또는 상호작용, 그리고 타입, 이미지, 색상, 형태를 하나로 묶는 하나의 시각적 아이디어를 말하십시오. 각 답변은 결정(예: "키가 큰 숫자로 채워진 전체 세트가 상단 1/3을 차지함")을 명명해야 하며, 형용사(예: "현대적이고 깔끔한")를 사용해서는 안 됩니다. 아이디어가 대부분의 유사한 앱이 이미 어떻게 보이는지 설명한다면, 그것은 아직 아이디어가 아닙니다.
- 히어로 모멘트 결정하기. 이 화면이 제품의 한두 가지 히어로 모멘트(가장 감정적이거나 가장 중심적인 상호작용) 중 하나인가요? 그렇다면 여러 전술이 어떻게 결합되는지 계획하십시오. 아니라면 차분하게 유지하십시오 (Google).
- 색상 소스 선택하기. 동적(배경화면), 브랜드(생성된 구성표), 또는 콘텐츠 기반(화면의 이미지에서) 중 선택하십시오. 섹션 4를 참조하십시오.
- 순위에 따라 강조 분배하기. 기본 목표가 가장 많은 강조를 받으며, 일반적으로 크기가 먼저입니다. 보조 목표는 더 적은 전술을 받고, 3차 목표는 컨테이닝과 타입을 받습니다 (Google). 콘텐츠가 제품 자체일 경우 화면을 지배할 수 있지만, 기본 작업이 명확하게 유지되어야 합니다.
- 섹션 9의 테이블에서 컴포넌트 선택하기. 이전 Material 기억에 의존하지 마십시오.
- 적응 질문에 답하기. 렌더링할 각 크기 클래스(컴팩트; 중간 또는 확장; 대형 또는 초대형)에 대해, 추가 공간이 무엇을 드러내는지 말하십시오: 두 번째 창, 확장된 레일, 더 많은 세부 정보. references/layout.md의 다섯 가지 질문을 사용하십시오. "무엇이 드러나야 하는가?"로 시작하십시오. 탐색은 일관되게 유지됩니다: 더 큰 레이아웃에 레일이 있으면 컴팩트에는 동일한 대상에 대한 탐색 모음이 있습니다. 미디어 플레이어와 같은 제어 기반 화면의 경우 제어가 재배치되고 콘텐츠가 드러납니다. 더 큰 레이아웃이 단순히 휴대폰 콘텐츠를 더 넓게 펼친 것이라면 제대로 답변한 것이 아닙니다: "추가 공간이 있다고 해서 같은 것을 더 크게 만드는 것만 의미하는 것은 아닙니다." (Google)
그런 다음 화면을 구성하고(섹션 8), 빌드한 후 렌더링된 결과에 화면 점검을 실행하십시오.
1. 테마 설정
Expressive는 androidx.compose.material3:material3 1.5.0-alpha 이상이 필요합니다. 안정적인 1.4.0에는 이러한 API가 거의 없습니다. 기억에 의존하지 말고 Maven 메타데이터에서 최신 1.5.x 버전을 확인하십시오; 알파 API는 릴리스 간에 여전히 변경됩니다. 현재 알파는 compileSdk 37 및 Android Gradle Plugin 9.1 이상도 필요로 합니다.
@Composable
fun AppTheme(dark: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {
val context = LocalContext.current
val colorScheme = when {
Build.VERSION.SDK_INT >= 31 -> if (dark) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
dark -> darkColorScheme()
else -> expressiveLightColorScheme()
}
MaterialExpressiveTheme(
colorScheme = colorScheme,
motionScheme = MotionScheme.expressive(),
typography = AppTypography, // Google Sans Flex 보이스 + 선택적 브랜드 서체, 섹션 5 참조
content = content,
)
}
expressiveDarkColorScheme는 없습니다;darkColorScheme()또는 생성된 다크 스킴을 사용하십시오.MaterialShapes,toShape(),LoadingIndicator,ContainedLoadingIndicator는 여전히@OptIn(ExperimentalMaterial3ExpressiveApi::class)가 필요합니다. 여기의 다른 모든 것은 1.5.0 알파에서 실험적이지 않습니다.- 전체 설정, 시드 스킴, 사용자 정의 타입 스케일, 형태 모핑, 모션 사양, 간격, 버전 노트: 테마를 설정하거나 변경할 때는 references/theming.md를 읽으십시오.
2. 강조와 계층 구조
강조는 사람들이 기본 동작을 찾는 방법입니다: 더 큰 주요 동작과 의도적인 계층 구조는 오류를 줄이고 주요 UI 요소를 더 빨리 찾을 수 있게 합니다 (Google).
- 크기는 가장 큰 레버이며, 상대적입니다. "가장 중요한 동작 또는 주요 CTA는 가장 큰 요소여야 합니다" (Google): 더 큰 주요 동작은 오류를 줄이고 사용자 만족도를 높이므로, 주된 동작은 주변 동작을 이끌어야 하며, 그 크기가 무엇이든 상관없습니다. 콘텐츠는 그것과 경쟁하지 않습니다: 요약 카드나 목록 행이 물리적으로 더 클 수 있습니다. 가장 강력한 채움(작은 버튼; FAB의 경우 Google의 "대부분의 상황에서 중간 FAB 권장")을 가진 컴포넌트의 기본 크기에서 시작하여 동료를 이끌기에 충분할 때까지만 키우십시오; 화면당 하나의 초점이며, 모든 것이 크면 아무것도 크지 않습니다. 그룹화된 동작은 기본적으로 하나의 크기를 공유하며("표준 그룹의 모든 버튼은 같은 크기여야 함"), 주된 동작은 채움 또는 형태를 통해 이끕니다: Google의 그룹 규칙은 "가장 크고, 가장 넓거나, 시각적으로 가장 두드러지는 것"입니다. 초대형은 플레이어나 호흡 세션과 같이 제어가 주도하는 히어로에 속하며, 여기서 제어는 화면의 콘텐츠입니다. 레이블이 최소 크기를 설정합니다: Google은 "레이블 텍스트를 자르거나 줄바꿈하지 마십시오"라고 말하며 컨테이너는 "레이블 텍스트보다 좁아서는 안 됩니다." 레이블이 선택된 크기의 컨테이너(휴대폰 너비 카드, 창)에서 한 줄에 맞지 않으면 1~3단어로 줄이거나, 버튼에 더 많은 공간을 주거나, 한 단계 아래 크기로 이동하십시오 (Google: 크기는 "다른 중단점에서" 변경될 수 있으며, 강조는 "크기, 색상 또는 형태를 통해" 옵니다).
- 배치: 손과 눈이 이미 있는 곳에 주요 동작을 두십시오. Google의 이메일 연구: 작은 상단 표시줄 아이콘에서 키보드 바로 위의 더 큰 버튼(
secondary로)으로 보내기 버튼을 이동하자 사람들이 4배 더 빨리 찾았습니다; Aura의 홈 화면은 초대형 시작 버튼을 아래쪽, 세로 흐름의 마지막에 둡니다. 상호작용과 콘텐츠가 필요한 공간에서 위치를 선택하십시오 (기본값). - 기본 동작은 가장 강력한 채움을 받습니다 (Google: 기본 역할은 중요한 CTA에 사용됩니다; 채움 버튼은 드물게 사용). 보조 동작은 토널 또는 표준입니다; 즐겨찾기와 같은 토글은 두 번째로 큰 채움으로 주요 제어와 경쟁하지 않고, 채워진 아이콘 또는 토널 컨테이너로 상태를 표시합니다.
- 역할 간 대비, 하나의 역할을 모든 곳에 사용하지 않음:
primary는 주요 동작,secondary또는secondaryContainer는 지원 제어,tertiary는 상태 또는 강조에 사용합니다. 모든 것에primary와primaryContainer를 사용하면 화면이 평평해집니다. - 컨테이닝: 관련 항목을 컨테이너에 그룹화하십시오; 가장 중요한 콘텐츠에 "넉넉한 공간과 가장 밝은 표면"을 제공하십시오.
- 요약은 작업을 지원하며, 그것보다 우선하지 않습니다. 기본 목표가 목록에 대한 작업(습관 체크, 메시지에 답장)일 때, 다음 실행 가능한 항목은 화면에서 가장 매력적으로 유지되어야 합니다. 상태 카드는 굵게 할 수 있지만, 실행 가능한 행에는 명확한 컨테이너를 제공하고 완료된 항목은 뒤로 물러나게 하십시오(더 차분한 색상, 강한 채움 없음), 섞지 말고 상태별로 그룹화하십시오 (섹션 8). 선택 강조는 사용자가 선택한 것을 위한 것이지, 완료된 것을 위한 것이 아닙니다.
- 작업 순서: 먼저 계층 구조(크기, 색상, 간격, 배치, 컨테이닝)를 구축한 다음, 성공이나 진행을 강조하기 위해 고유한 강조(형태, 스케일, 모프)를 추가하십시오.
Google의 작업 예시: Aura 호흡 앱
각 화면은 목표 순위에 따라 강조를 분배합니다. 이를 추론 템플릿으로 사용하십시오.
| 화면 | 순위 | 강조 |
|---|---|---|
| 홈 | 기본: 세션 시작 | 부드러운 표면 위에 어두운 primary의 초대형 "호흡 시작" 버튼, 화면 아래쪽. 설정은 secondary의 목록 항목으로 그룹화. 일일 메시지는 부드러운 컨테이너에, 가장 적은 강조. |
| 세션 | 히어로 모멘트 | 화면을 채우는 꽃 모양(MaterialShapes.Flower 및 Sunny)이 봄 모션으로 각 호흡에 따라 커지고 작아짐; 흡기시 생생한 노란색; 작은 레이블에 비해 거대한 카운트다운 숫자; 아래쪽에 작은 일시 중지/중지 버튼; 탐색 모음 숨김. |
| 보고서 | 보조 | "인지 부하를 줄이기 위해" 더 적은 전술: 균일한 꽃 모양의 메트릭, 강조된 숫자, 중간(초대형 아님) 완료 버튼. |
| 진행 | 3차 | 미묘함: primary의 주요 데이터, 작은 보조 모양의 완료된 일, "스캔하기에는 충분히 크지만 지배하지는 않는" 숫자. |
v1에서 v2로의 교훈: 유사한 크기와 일관성 없는 색상의 그룹화되지 않은 설정은 주의를 위해 경쟁했습니다; 그것들을 하나의 초대형 버튼 위에 그룹화하면 "혼란에서 차분함으로" 바뀌었습니다.
3. 히어로 모멘트와 절제
"히어로 모멘트는 여러 표현 전술을 사용하여 예측 가능하거나 균일하게 적용된 디자인 아이디어에서 벗어납니다."
- 히어로 모멘트는 타입, 형태, 색상, 모션, 유연한 컴포넌트를 제품의 주요 상호작용(전화 다이얼러, 미디어 플레이어, 완료된 목표, 호흡 세션)에 계층화합니다. 질문: 감정적으로 영향력이 있는가? 그리고 주요 상호작용인가?
- 제품당 한두 개. 그것들은 "짧고, 즐겁고, 놀랍고, 예상치 못한" 것입니다; 그 이상은 압도적입니다.
- 보조 화면은 더 적은 전술을 사용합니다. 모든 곳에서 모든 전술을 결합하지 마십시오.
- 히어로 모멘트에서는 하나의 사용자 정의 항목이 움직입니다: 형태가 애니메이션되는 동안 텍스트를 안정적으로 유지하십시오 (Google). 내장 컴포넌트 모프(누를 때 모양이 변하는 버튼)는 포함되지 않습니다.
- 콘텐츠가 제품일 때, 콘텐츠가 히어로입니다. 플레이어, 갤러리, 여행에서 앨범 아트나 사진에 스케일을 주고 그 색상이 화면을 설정하도록 하십시오. 라이브러리 모양 마스크, 전체 블리드, 이미지 위에 오버레이된 제목은 옵션이며 요구 사항이 아닙니다: 주변 구성이 아이디어를 전달할 때 일반적인 둥근 자르기도 마찬가지로 강력합니다.
- 익숙한 패턴을 유지하십시오. Expressive는 패턴을 스타일링하며, 대체하지 않습니다. Google의 테스트에서 산점된 앨범 아트로 재구축된 재생 목록은 "현대적이고 흥미로워 보였지만" 사람들은 그것을 재생 목록으로 인식하지 못했고, 이메일 동작에서 텍스트 레이블을 제거하는 것은 사용성을 해쳤습니다. 문맥도 중요합니다: 미디어 플레이어에 적합한 것이 은행 앱에는 적합하지 않을 수 있습니다.
- "어떤 감정도 명확성의 부족을 보상할 수 없습니다." Expressive는 이미 작동하는 화면을 날카롭게 합니다; 혼란스러운 화면을 구하지는 않습니다.
4. 색상
- 생성기가 팔레트를 만듭니다; 당신은 역할을 할당합니다. Material의 색상 유틸리티는 하나의 소스 색상을 강조, 표면, 밝음, 어두움 역할로 변환합니다 (Google). 생성된 팔레트를 그대로 받아들이고 디자인 노력을 어떤 요소가 어떤 역할을 받을지에 집중하십시오.
- 동적 (배경화면)은 Google의 권장 사항이며 개인화를 제공합니다. M3 Expressive 업데이트는 동적 색상을 소스에서 더 풍부하게 만들었습니다("모든 색조에서 더 높은 채도"); 앱은 자동으로 얻습니다. 앱은 휴대폰의 나머지 부분과 색조를 공유하므로, 정체성은 계층 구조, 형태, 타입에서 비롯됩니다.
- 브랜드는 앱에 고유한 정체성을 부여합니다: Material Theme Builder로 브랜드 색상에서 생성된 스킴, 또는 런타임에 기본 팔레트 스타일로 MaterialKolor를 사용합니다 (테마 지정 참조). "더 표현적으로" 보이기 위해 팔레트 스타일을 높이지 마십시오: MaterialKolor의
PaletteStyle.Expressive는 M3 Expressive와 관련 없는 색조 이동 스킴 변형이며, 팔레트를 브랜드의 색조에서 멀어지게 합니다. - 콘텐츠 기반은 화면의 이미지에서 파생된 색상으로 포함된 영역을 채색합니다. Google 포토의 사진 색상 동적 테마 또는 음악 플레이어의 앨범 아트 색상이 예입니다.
dominantColor()(또는 Coil 3의rememberDominantColor)는 적절하지만 프로덕션에서는palette라이브러리 또는 서버 측 추출을 고려하십시오. 이는 히어로 모멘트 또는 이미지가 제품인 화면(갤러리, 플레이어)을 위한 것입니다.
- 기본 색상은 색조입니다, 정확한 일치는 아닙니다. 동적 및 콘텐츠 기반 색상은 생성기에서 예측할 수 없으므로, 기본 색상에 고대비 텍스트(예: 검은색 위의 흰색)를 사용하는 것은 안전하지 않습니다. 대신
onPrimary를 사용하십시오. 기본 색상의 텍스트(예: 흰색 버튼의 검은색 아이콘)에는 항상onPrimary또는contentColorFor를 사용하십시오. - 표면 역할을 이해하십시오.
surface,surfaceVariant,surfaceDim,surfaceBright,surfaceContainer(가장 높은에서 가장 낮은 표면 높이)는 Material 3에서 표면이 색상인 방법입니다.surfaceContainer(가장 높음)는 카드용이며,surface는 배경용입니다. 동적 테마는 일반적으로 어두운 표면 톤을 사용합니다; 명시적으로 제어하려면lightColorScheme에surfaceTint를 사용하거나 어두운 표면 색상을 직접 설정하십시오. - 상태(오류, 비활성화, 포커스)는 투명도와 불투명도를 통해 옵니다: 비활성화된 컴포넌트는 0.38 알파, 오류는 0.82 알파. 구현은 상태 계층을 자동으로 처리하는 M3 컴포넌트에 맡기고, 사용자 정의 컴포넌트에서만 수동 오버레이를 사용하십시오.
- 강조는 대비이며, 채도가 아닙니다. 표면에서 강조 색상으로 갈 때 대비를 유지하십시오. 가장 밝은 표면(보통
surfaceContainer가장 높음)과 가장 어두운 텍스트(onSurface) 사이의 대비 비율은 WCAG AA(4.5:1)를 충족해야 합니다. 기본은 7:1(AAA)을 목표로 합니다. 동적 색상은 일반적으로 이것을 처리하지만, 브랜드 스킴을 수동으로 조정할 때는 WCAG Contrast Checker를 사용하여 확인하십시오. - theme.md 참조는 palettestyle, 사용자 정의 스킴, 색상 인식, 표면 높이, 스킴 생성 지연에 대한 더 많은 세부 정보를 제공합니다.
5. 타이포그래피
Expressive는 미리 정의된 스타일과 보이스를 결합합니다: "서체의 다양한 표현력을 활용하는 구조화된 방법" (Google). 보이스는 동일한 서체 계열 내의 굵기, 너비, 및 기울임꼴의 세트입니다. Google Sans Flex는 9개의 보이스(Thin에서 Black까지 5개의 굵기 × 3개의 너비)를 제공합니다. 하나의 브랜드 서체를 추가하여 정체성을 더할 수 있지만, 화면당 1~2개의 서체와 각 보이스 간에 명확한 계층 구조를 유지하십시오.
타입 스케일
| 역할 | Google Sans Flex 굵기 | 크기 | 사용 예 |
|---|---|---|---|
| Display | Black 또는 Bold | 57sp | 히어로 순간: 환영, 큰 숫자. 다른 곳에서는 드물게 사용. |
| Headline | Medium | 32sp | 섹션 제목, 히어로가 아닌 화면의 주요 텍스트. |
| Title | SemiBold | 22sp | 카드 제목, 탐색 표시줄 레이블. |
| Label | Medium | 14sp | 버튼 텍스트, 목록 항목 레이블. |
| Body | Regular | 16sp | 단락, 설명 텍스트. |
- Google Sans Flex는 Android용 기본 서체입니다. Wear OS는
wear-compose테마의 일부인 Google Sans Text를 사용합니다. - 타입은 강조를 전달합니다: 굵기와 크기로 계층 구조를 만드십시오. 표준 Material 타입 스케일을 사용하지만, 보이스(굵기 and 너비) 간의 간격을 조정하여 더 큰 대비를 만들 수 있습니다. Google: "타입 스케일 간의 간격은 계층 구조를 만듭니다."
- 읽기 쉬운 줄 길이: 본문 텍스트의 경우 줄당 45~75자로 제한하십시오. 더 긴 텍스트는 여러 열을 사용하거나 텍스트를 더 작은 청크로 나누십시오.
- 사용자 정의 보이스: 브랜드 서체를 추가하는 경우, 시각적 소음을 피하기 위해 하나의 굵기(예: Bold)로만 사용하고 Google Sans Flex 보이스와 명확히 구분하십시오. 브랜드 서체에 대한
@font-face를res/font/에 정의하고FontFamily로 설정하십시오. - 접근성: 최소 16sp 본문 텍스트를 목표로 하고, 타입 스케일이 대비 요구 사항을 충족하는지 확인하십시오. 시스템 글꼴 크기 조정을 존중하십시오.
- 타이포그래피 참조:
AppTypography설정, 사용자 정의 보이스,PlatformTextStyle,lineHeight,letterSpacing에 대한 자세한 내용은 references/theming.md를 참조하십시오.
6. 형태
Expressive 형태는 정적인 Material 3 모양 시스템에 애니메이션과 변화를 추가합니다. MaterialShapes는 Flower, Sunny, Squircle, Pill, RoundedRect, CutCorner, Angled, Chamfered를 제공합니다. 형태는 MaterialExpressiveTheme의 shapes 매개변수로 설정하거나, toShape()로 인라인으로 적용할 수 있습니다.
- 한 화면에 하나의 지배적인 형태. 다양한 형태를 혼합하면 시각적 소음이 발생합니다. 하나의 형태를 선택하고(예: 모든 카드에 RoundedRect, FAB에 Pill) 다른 모든 것에 일관되게 적용하십시오.
- 형태는 의미를 전달합니다. 부드러운 형태(꽃, 동그라미)는 따뜻함과 접근성을 암시합니다; 각진 형태(찍힌 모서리, 경사짐)는 정밀함이나 힘을 암시합니다. 형태를 콘텐츠의 톤과 일치시키십시오.
- 모핑:
animateShape및shapeTransition은 한 형태에서 다른 형태로 부드럽게 전환되며, 히어로 모멘트(예: 버튼이 누를 때 모양이 변하는) 또는 상태 변경(예: 완료된 작업이 체크 표시로 변하는)에 사용합니다. 모핑은 과도하게 사용하지 마십시오: 한 번의 전환에서 두 개 이상의 모핑하지 마십시오 (Google). - 확장된 형태:
toShape()는 선택적 너비 및 높이 매개변수를 허용하여 형태가 전체 컨테이너 또는 카드를 채울 수 있습니다. 이는 진행 표시기, 로딩 상태, 또는 강조된 통계를 위한 것입니다. - 사용자 정의 형태: 복잡한 브랜드 형태의 경우
GenericShape를 사용하거나Shape인터페이스를 구현하십시오. Expressive의 내장 형태에 묶여 있지 않습니다; 독점 형태를 사용할 때는 정체성의 일관된 적용을 보장하십시오.
7. 모션
Expressive 모션은 Material 3 모션 시스템 위에 구축되며, MotionScheme.expressive()로 활성화됩니다. 이는 가속/감속, 지속 시간, 경로에 대한 기본값을 제공합니다.
- 모션은 목적을 제공합니다. 단순한 장식이 아닌, 전환, 상태 변경, 또는 사용자 행동의 확인을 안내합니다. Google: "모션은 의미가 있어야 합니다."
- 지속 시간: 짧은 전환(100
200ms)은 일반 상호작용(버튼 누름, 목록 항목 선택)에 사용됩니다. 더 긴 전환(300500ms)은 히어로 모멘트 또는 콘텐츠가 크게 변경될 때(화면 전환, 모달 표시)에 사용됩니다. - 경로: 직선 경로는 신속하고 직접적인 느낌을 줍니다; 곡선 경로(호, 원호)는 우아함이나 놀라움을 더합니다. 경로는 동작의 캐릭터와 일치해야 합니다.
- 상태 전환:
animate*AsState함수(예:animateColorAsState,animateDpAsState)를 사용하여 컴포넌트 간에 부드럽게 전환하십시오.TransitionAPI는 여러 속성(색상, 크기, 형태)을 동시에 애니메이션하는 데 사용됩니다. - 모션은 히어로 모멘트를 위한 것입니다. 모든 곳에서 모션을 사용하지 마십시오; 핵심 상호작용과 상태 변경을 위해 저장하십시오. 보조 화면은 모션을 최소로 사용하거나 전혀 사용하지 않아야 합니다.
- 성능: 모션을 가볍게 유지하십시오. 애니메이션당 하나의 속성 애니메이션을 목표로 하고, 복잡한 계층 구조 애니메이션(예: 목록 항목이 개별적으로 페이드 인되는)을 피하십시오. GPU 프로파일링 도구를 사용하여 프레임 속도를 확인하십시오.
8. 화면 구성
화면을 구성하려면 표준 Compose 레이아웃 원칙을 따르되, Material 3 Expressive 컴포넌트를 사용하십시오.
- 표준 컴포넌트 사용:
Scaffold,TopAppBar,NavigationBar,NavigationRail,BottomSheet,FloatingActionButton과 같은 M3 기본값부터 시작하십시오. 사용자 정의 컴포넌트는 필요할 때만 사용하십시오. - 표면과 높이:
Surface와Elevation을 사용하여 계층 구조를 만드십시오. 더 높은 중요도는 더 높은 높이(더 큰 그림자)를 얻습니다. 표면 높이의 일반적인 순서: 표면 < 표면 컨테이너 < 카드 < 모달. - 간격: 일관된 간격 시스템을 사용하십시오(예:
MaterialTheme.spacing). Expressive는 기본 간격을 정의하지 않으며, 8dp 그리드를 권장합니다. 간격은 밀도 통일성을 유지하려면 모든 중단점에서 일관되어야 하지만, 더 큰 화면에서는 콘텐츠 사이에 더 많은 공간이 있을 수 있습니다. - 적응형 레이아웃:
WindowSizeClass라이브러리(WindowWidthSizeClass,WindowHeightSizeClass)를 사용하여 사용 가능한 공간에 따라 레이아웃을 조정하십시오. 컴팩트(<600dp), 중간(600~840dp), 확장(>840dp)의 세 가지 크기 클래스를 지원하십시오. 참조 적응 레이아웃 패턴은 references/layout.md에 있습니다.- 컴팩트: 전화기와 같은 단일 창 레이아웃, 종종 하단 탐색 모음.
- 중간: 접이식 또는 소형 태블릿; 레일이 있는 옆 창 또는 목록-디테일 패턴.
- 확장: 태블릿, 데스크톱; 여러 창(지원 창, 세부 정보 패널)이 있는 전체 화면 레이아웃.
- 내비게이션: 내비게이션 구조는 모든 크기 클래스에서 일관되게 유지하십시오. 컴팩트는 하단 내비게이션 바를 사용합니다; 중간과 확장은 내비게이션 레일을 사용하지만 동일한 대상을 제공합니다. Google: "내비게이션 패턴은 크기 클래스 간에 일관되어야 합니다."
- Wear OS: Wear OS 화면의 경우 references/wear-os.md를 따르고,
CurvedText,ScalingLazyColumn,ScaffoldwithTimeText를 사용하십시오. Wear에서는 탐색 서랍과 작업 서랍에 제한이 있습니다.
9. 컴포넌트 선택 테이블
| 구성 | Material 3 컴포넌트 | Expressive 확장 | 노트 |
|---|---|---|---|
| 주요 CTA | Button (filled) | FilledTonalButton, FloatingActionButton | 주요 동작은 가장 강력한 채움을 받습니다. FAB는 중간 크기(56dp)가 기본입니다. |
| 보조 CTA | OutlinedButton, TextButton | FilledTonalButton (토널) | 주요와 경쟁하지 않습니다. |
| 수동 토글 | Switch, Checkbox, RadioButton | FilledIconButton, ToggleButton | 상태 표시기; 작업 토글에는 FilledIconButton을 사용하십시오. |
| 목록 | LazyColumn, ListItem | LazyColumn + Card (요약) | ListItem은 간단한 행에 사용하십시오. Card는 요약 및 그룹화에 사용하십시오. |
| 카드 | Card (Elevated, Filled, Outlined) | Card + ExpressiveShape | 형태는 의미를 전달합니다. Elevated 카드는 더 높은 중요도를 가집니다. |
| 탭 | TabRow, ScrollableTabRow | TabRow | 탭은 기본 탐색입니다; 콘텐츠 전환을 위한 HorizontalPager와 결합하십시오. |
| 다이얼로그 | AlertDialog, DatePickerDialog, TimePickerDialog | AlertDialog | 다이얼로그는 모달이며 전체 창을 차지해서는 안 됩니다. |
| 바텀 시트 | ModalBottomSheet, StandardBottomSheet | ModalBottomSheet | 모달 바텀 시트는 옵션 또는 추가 정보에 사용하십시오. |
| 진행 표시기 | LinearProgressIndicator, CircularProgressIndicator | ContainedLoadingIndicator, LoadingIndicator | ContainedLoadingIndicator는 형태(예: Flower)로 채워집니다. |
| 탐색 | NavigationBar (컴팩트), NavigationRail (중간/확장) | NavigationDrawer | 내비게이션은 일관성을 유지하십시오. |
| 슬라이더 | Slider | Slider + ExpressiveShape | 미디어 컨트롤 및 볼륨 슬라이더에 사용하십시오. |
| 스낵바 | Snackbar, SnackbarHost | Snackbar | 작업 확인 및 오류 메시지를 위해 사용하십시오. |
| 앱 바 | TopAppBar (CenterAligned, Small, Medium, Large) | TopAppBar | 화면 제목 및 작업에 사용하십시오. |
| 이미지 | Image (Coil 또는 Glide 사용) | AsyncImage (Coil) | 반응형 이미지 로딩을 위해 Coil 3를 사용하십시오. |
화면 점검
화면을 빌드한 후, 다음 점검 목록을 실행하십시오. 각 항목에 대해 예/아니오로 답변하고, 아니오인 경우 수정하십시오.
- 목표 순위가 명확한가? 기본 작업이 눈에 띄고 보조 작업은 지원합니다. 히어로 모멘트는 여러 전술을 결합합니다; 보조 화면은 더 적은 전술을 사용합니다. (Google)
- 색상이 의도적으로 사용되었는가? 동적, 브랜드, 또는 콘텐츠 기반? 오류 상태는 올바른 투명도를 사용하는가? 강조가 대비를 통해 이루어지며 채도를 통하지 않는가? (기본값)
- 타이포그래피가 계층 구조를 만드는가? 굵기, 크기, 간격이 명확한 계층 구조를 만드는가? 읽기 쉬운 줄 길이(본문 텍스트 45~75자)를 유지하는가? 접근성 요구 사항을 충족하는가? (기본값)
- 형태가 일관되고 의미 있는가? 화면당 하나의 지배적인 형태가 사용되는가? 형태가 콘텐츠의 톤과 일치하는가? 히어로 모멘트 외에는 모핑이 사용되지 않는가? (기본값)
- 모션이 목적을 제공하는가? 모션이 단순한 장식이 아닌 전환을 안내하는가? 지속 시간이 상호작용에 적절한가? 히어로 모멘트는 모션을 과도하게 사용하지 않는가? (기본값)
- 레이아웃이 모든 크기 클래스에 적응하는가? 컴팩트, 중간, 확장이 모두 처리되는가? 내비게이션이 일관되게 유지되는가? 추가 공간이 단순히 같은 콘텐츠를 늘리는 대신 콘텐츠를 드러내는가? (Google)
- 컴포넌트가 올바르게 선택되었는가? 주요 CTA가 가장 강력한 채움을 받는가? 보조 동작이 주요와 경쟁하지 않는가? 토글이 상태를 올바르게 표시하는가? (기본값)
- 간격이 일관된가? 8dp 그리드가 사용되는가? 간격이 밀도를 유지하는가? 더 큰 화면에서 콘텐츠 사이에 충분한 공간이 있는가? (기본값)
- 접근성 요구 사항이 충족되는가? 대비 비율이 최소 4.5:1(AA)인가? 텍스트 크기가 시스템 글꼴 크기 조정을 존중하는가? 모든 상호작용 요소가 충분히 큰 터치 대상(48dp)을 가지고 있는가? (기본값)
- 화면이 Material 3 Expressive 원칙을 따르는가? 강조가 의도적으로 사용되었는가? 히어로 모멘트가 여러 전술을 결합하는가? 콘텐츠가 제품일 때는 화면을 지배하는가? (Google)
참조
- references/theming.md: 테마 설정, 색상, 타이포그래피, 형태, 모션에 대한 자세한 내용.
- references/layout.md: 적응형 레이아웃 패턴, 크기 클래스, 내비게이션.
- references/wear-os.md: Wear OS 관련 지침.
- m3.material.io: Material 3 공식 문서.
- developer.android.com/design/ui: Android 디자인 가이드.
- wear-os-design-guide: Wear OS 디자인 가이드.