Jetpack Compose를 사용한 Material Theming

1. 시작하기 전에

Material Design은 개발자가 Android 및 기타 모바일과 웹 플랫폼을 위한 고품질 디지털 환경을 빌드할 수 있도록 Google에서 만든 디자인 시스템입니다. 물체가 빛을 반사하고 그림자를 드리우는 방식을 비롯하여 실제 세계와 그 질감에서 영감을 받아 고안된 Material Design은 읽기 쉽고 매력적이며 일관된 방식으로 앱 UI를 빌드하는 방법에 관한 가이드라인을 제시합니다.

이 Codelab에서는 앱에서 Material Design을 사용할 수 있도록 지원하는 Material Theming에 관해 알아보고 색상, 서체, 도형 맞춤설정에 관해 안내합니다. 앱의 맞춤설정은 원하는 만큼 적게 또는 많이 적용할 수 있습니다. 상단 앱 바를 추가하여 앱 이름과 아이콘을 표시하는 방법도 알아봅니다.

기본 요건

  • 문법, 함수, 변수를 비롯한 Kotlin 언어 관련 지식
  • Compose에서 패딩이 있는 행과 열을 비롯한 레이아웃을 빌드할 수 있음
  • Compose에서 간단한 목록을 만들 수 있음

학습할 내용

  • Compose 앱에 Material Theming을 적용하는 방법
  • 앱에 맞춤 글꼴을 추가하는 방법
  • 앱에 맞춤 색상 팔레트를 추가하는 방법
  • 앱의 요소에 맞춤 도형을 추가하는 방법
  • 앱에 상단 앱 바를 추가하는 방법

빌드할 항목

  • Material Design 권장사항이 적용된 멋진 앱을 빌드합니다.

필요한 항목

  • Android 스튜디오 최신 버전
  • 시작 코드와 글꼴을 다운로드하기 위한 인터넷 연결

2. 앱 개요

이 Codelab에서는 반려견 목록을 표시하고 Material Design을 사용하여 멋진 앱 환경을 구현하는 Woof 앱을 만듭니다.

밝은 테마의 맞춤 상태 표시줄이 있는 Woof 앱을 보여주는 이미지입니다.

Woof 앱은 디자이너가 앱의 색상 팔레트, 서체, 도형을 선택하여 디자인했습니다. 디자이너와 협력하기 어려운 개발자도 있다는 사실을 잘 알고 있습니다. 이 Codelab에서는 Material Theming을 사용하면 무엇을 할 수 있는지 알아보겠습니다. Material Theming을 사용하여 앞으로 만들 앱의 디자인과 분위기를 개선하는 용도로 이 Codelab을 활용하세요.

다음은 디자이너가 적용한 디자인 사양입니다. 밝은 테마와 어두운 테마의 시각적 디자인이 나와 있습니다.

앱 디자인:

밝은 테마

어두운 테마

밝은 테마의 맞춤 상태 표시줄이 있는 Woof 앱을 보여주는 이미지입니다.

색상 팔레트

다음은 디자이너가 적용한 밝은 테마와 어두운 테마의 색상 팔레트입니다.

밝은 테마:

색상

이름

16진수 색상

슬롯

Grey50 색상을 보여주는 이미지입니다.

Grey50

#F8F9FA

primary

Green50 색상을 보여주는 이미지입니다.

Green50

#E6F4EA

surface

Green100 색상을 보여주는 이미지입니다.

Green100

#CEEAD6

background

Grey700 색상을 보여주는 이미지입니다.

Grey700

#5F6368

secondary

Grey900 색상을 보여주는 이미지입니다.

Grey900

#202124

onSurface

Grey900 색상을 보여주는 이미지입니다.

Grey900

#202124

onPrimary

어두운 테마:

색상

이름

16진수 색상

슬롯

White 색상을 보여주는 이미지입니다.

White

#FFFFFF

primary

Grey100 색상을 보여주는 이미지입니다.

Grey100

#F1F3F4

onSurface

Grey100 색상을 보여주는 이미지입니다.

Grey100

#F1F3F4

onPrimary

Cyan700 색상을 보여주는 이미지입니다.

Cyan700

#129EAF

surface

Cyan900 색상을 보여주는 이미지입니다.

Cyan900

#007B83

background

Grey900 색상을 보여주는 이미지입니다.

Grey900

#202124

secondary

서체

다음은 디자이너가 선택한 앱의 글꼴입니다.

제목

글꼴

글꼴 두께

크기

h1

Abril Fatface 글꼴을 보여주는 이미지입니다.

Normal

30sp

h2

Montserrat 글꼴을 보여주는 이미지입니다.

Bold

20sp

h3

Montserrat 글꼴을 보여주는 이미지입니다.

Bold

14sp

body1

Montserrat 글꼴을 보여주는 이미지입니다.

Normal

14sp

테마 파일

Theme.kt 파일은 색상, 서체, 도형으로 정의되는 앱 테마에 관한 모든 정보를 담고 있는 파일입니다. 이 Codelab에서는 Theme.kt 파일을 한 번만 수정하지만, 개발자가 반드시 알아두어야 하는 파일입니다. 이 파일에는 앱의 색상, 서체, 도형을 설정하는 WoofTheme() 컴포저블이 있습니다.

@Composable
fun WoofTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {
   val colors = if (darkTheme) {
       DarkColorPalette
   } else {
       LightColorPalette
   }

   MaterialTheme(
       colors = colors,
       typography = Typography,
       shapes = Shapes,
       content = content
   )
}

MainActivity.ktWoofTheme()가 추가되어 Material Theming을 적용합니다.

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

DefaultPreview()를 살펴보세요. Preview 탭의 Material Theming을 적용하도록 WoofTheme()가 추가됩니다.

@Preview
@Composable
fun DefaultPreview() {
   WoofTheme(darkTheme = false) {
       WoofApp()
   }
}

3. 시작 코드 가져오기

  1. 프로젝트에 제공된 GitHub 저장소 페이지로 이동합니다.
  2. Code(코드) 버튼을 클릭합니다. 대화상자가 열립니다.

1debcf330fd04c7b.png

  1. 대화상자에서 HTTPS 탭을 클릭한 다음 URL 옆에 있는 d80cda5fcac5cc83.png 버튼을 클릭하여 복사합니다. Android 스튜디오에서 이 URL을 사용합니다.

52117cef9280e2c3.png

  1. Android 스튜디오가 열려 있지 않으면 Android 스튜디오를 열고 Welcome to Android Studio 창에서 Get from VCS를 클릭합니다.

38e3cb13f6cbf3b8.png

  1. Android 스튜디오가 이미 열려 있으면 File > New > Project from Version Control을 선택합니다.

eb859f5f2f920118.png

  1. Get from Version Control 창의 Version control 메뉴에서 Git을 선택합니다.

c1ff21b37a87da88.png

  1. URL 텍스트 상자에 GitHub 저장소 페이지에서 복사한 링크를 입력합니다.
  2. Directory 메뉴에서 GitHub 저장소의 소스 코드를 클론할 디렉터리를 선택합니다.

d872acd8fb88d532.png

  1. Clone을 클릭합니다.
  2. Android 스튜디오에 프로젝트가 다운로드되어 열릴 때까지 기다립니다.
  3. Android 스튜디오의 탐색 메뉴에서 8de56cba7583251f.png 'Run app'을 클릭한 다음 앱이 제대로 빌드되는지 확인합니다.
  4. 탐색 메뉴에서 Git > Branches...를 클릭합니다.

3b3d9c44dcc1327a.png

  1. Remote Branches 섹션의 Git Branches 대화상자에서 앞서 받은 분기 이름을 선택하고 Checkout을 클릭합니다.

4d189e9e70df0234.png

  1. 분기를 전환해야 하는 경우 Git > Branches를 클릭한 다음 전환하려는 분기를 선택하고 Smart Checkout을 클릭합니다.

596d8337aba9e937.png

시작 코드 살펴보기

  1. Android 스튜디오에서 시작 코드를 엽니다.
  2. com.example.woof > data > Dog.kt를 엽니다. 여기에는 반려견의 사진, 이름, 나이, 취미를 나타내는 데 사용할 Dog data class가 있습니다. 앱의 데이터로 사용할 반려견 목록과 정보도 있습니다.
  3. res > drawable을 엽니다. 여기에는 앱 아이콘, 반려견 이미지, 아이콘 등 이 프로젝트에 필요한 모든 이미지 애셋이 있습니다.
  4. res > values > strings.xml을 엽니다. 여기에는 앱 이름, 반려견 이름, 설명 등 이 앱에서 사용할 문자열이 있습니다.
  5. MainActivity.kt를 엽니다. 여기에는 반려견 사진, 반려견 이름, 반려견 나이를 표시하는 간단한 목록을 만드는 코드가 있습니다.
  6. WoofApp()에는 DogItems를 표시하는 LazyColumn이 있습니다.
  7. DogItem()에는 반려견 사진과 관련 정보를 표시하는 Row가 있습니다.
  8. DogIcon()은 반려견 사진을 표시합니다.
  9. DogInformation()에는 반려견의 이름과 나이가 있습니다.

에뮬레이터/기기가 밝은 테마로 설정되었는지 확인하기

이 Codelab에서는 밝은 테마와 어두운 테마를 모두 사용하지만, Codelab은 대부분 밝은 테마로 진행됩니다. 시작하기 전에 기기/에뮬레이터가 밝은 테마로 설정되었는지 확인하세요.

앱을 밝은 테마로 보려면 에뮬레이터 또는 실제 기기에서 다음 단계를 따릅니다.

  1. 기기에서 설정 앱으로 이동합니다.
  2. 어두운 테마를 검색하여 클릭합니다.
  3. 어두운 테마가 사용 설정되어 있으면 사용 중지합니다.

시작 코드를 실행하여 반려견의 사진, 이름, 나이가 포함된 목록이 표시되는 것을 확인합니다. 기능상에는 문제가 없지만 별다른 디자인이 적용되어 있지 않습니다. 지금부터 디자인을 적용해 보겠습니다.

반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다.

4. 색상 추가

Woof 앱에서 가장 먼저 수정할 것은 색상 팔레트입니다.

색상 팔레트는 앱에서 사용하는 색상의 조합입니다. 색상 조합은 저마다 다양한 분위기를 냅니다. 이는 사람들이 앱을 사용할 때 느끼는 감정에 영향을 줍니다. 이 앱을 함께 디자인해 준 디자이너가 색상 팔레트도 선택해 주었습니다. Material Design 웹사이트의 색상 시스템 가이드에서 색상 팔레트와 이를 직접 생성하는 방법에 관해 자세히 알아볼 수 있습니다.

Android 앱에 색상을 추가할 때는 보통 Color.REDColor.PINK와 같은 항목을 사용했습니다. 그렇다면 짙은 파란색이나 청록색과 같은 특정 색상을 추가하려면 어떻게 해야 할까요?

Android 시스템에서 색상은 16진수 색상 값으로 표현됩니다. 16진수 색상 코드는 파운드(#) 문자로 시작하며 그 뒤에 해당 색상의 빨간색, 녹색, 파란색(RGB) 구성요소를 나타내는 6개의 문자 또는 숫자가 옵니다. 처음 두 개의 문자/숫자는 빨간색을, 다음 두 개는 녹색을, 마지막 두 개는 파란색을 나타냅니다.

색상을 만드는 데 사용되는 16진수를 보여주는 이미지입니다.

색상은 투명도(#00: 불투명도 0%(완전히 투명), #FF: 불투명도 100%(완전히 불투명))를 나타내는 알파 값(문자 및/또는 숫자)도 포함할 수 있습니다. 알파 값이 포함된 경우, 파운드(#) 문자 뒤의 16진수 색상 코드의 처음 두 문자가 알파 값입니다. 알파 값이 포함되지 않은 경우 알파 값이 100% 불투명도(완전히 불투명)인 #FF라고 간주됩니다.

다음은 몇 가지 16진수 색상 값의 예입니다.

색상

이름

16진수 색상

Black 색상을 보여주는 이미지입니다.

Black

#000000

Green 색상을 보여주는 이미지입니다.

Green

#72D98C

Blue 색상을 보여주는 이미지입니다.

Blue

#4285F4

White 색상을 보여주는 이미지입니다.

White

#FFFFFF

색상의 16진수 색상 코드를 기억할 필요는 없습니다. 색상 선택 도구를 사용하면 숫자가 알아서 생성됩니다. 이 Codelab에서는 정확한 색상을 안내합니다.

다음은 앱에서 사용하는 색상 팔레트입니다. 알파 값이 없으므로 색상이 100% 불투명도임을 알 수 있습니다.

밝은 테마:

색상

이름

16진수 색상

슬롯

Grey50 색상을 보여주는 이미지입니다.

Grey50

#F8F9FA

primary

Green50 색상을 보여주는 이미지입니다.

Green50

#E6F4EA

surface

Green100 색상을 보여주는 이미지입니다.

Green100

#CEEAD6

background

Grey700 색상을 보여주는 이미지입니다.

Grey700

#5F6368

secondary

Grey900 색상을 보여주는 이미지입니다.

Grey900

#202124

onSurface

Grey900 색상을 보여주는 이미지입니다.

Grey900

#202124

onPrimary

슬롯이란 무엇이고 어떻게 할당되는지 궁금하실 텐데요.

  • primary 색상은 앱의 화면과 구성요소에서 가장 자주 표시되는 색상입니다.
  • secondary 색상은 앱을 강조하고 구분하는 데 사용됩니다.
  • surface 색상은 카드, 시트, 메뉴와 같은 구성요소의 표면에 적용됩니다.
  • background 색상은 스크롤 가능한 콘텐츠 뒤에 나타납니다.
  • on 색상 요소는 팔레트의 색상 위에 나타나며, 주로 텍스트, 아이콘, 획에 적용됩니다. 우리의 색상 팔레트에는 surface 색상 위에 나타나는 onSurface 색상과 primary 색상 위에 나타나는 onPrimary 색상이 있습니다.

이러한 슬롯을 사용하면 관련 있는 구성요소에 비슷한 색상이 적용되는 일관된 디자인 시스템을 갖게 됩니다.

특정 구성요소는 색상 슬롯에 자동으로 매핑됩니다. 예를 들어 Surface 컴포저블의 배경색은 surface 슬롯에 자동으로 매핑됩니다. 즉, Surface 컴포저블에 surface 색상을 명시적으로 할당하지 않아도 앱에서 색상 테마를 설정하면 자동으로 이렇게 표시됩니다. 사용 가능한 색상 슬롯은 6개보다 많지만, 슬롯을 모두 다 할당할 필요는 없습니다. 앱 테마에 지정되지 않은 모든 색상에는 앱의 기본 테마를 정의하는 기준 Material 색상 테마에 정의된 색상이 적용됩니다.

색상에 대한 설명은 여기까지입니다. 이제 색상 팔레트를 앱에 적용해 볼 차례입니다.

테마에 색상 팔레트 추가하기

  1. Color.kt 파일을 엽니다. 이 파일은 앱의 색상 팔레트에 색상을 추가하는 데 사용됩니다. 기본 색상 팔레트에 매핑되는 몇 가지 색상이 이미 추가되어 있습니다. 기존에 추가되어 있는 색상 아래에 Woof 앱 색상 팔레트에 필요한 다음과 같은 새로운 색상을 추가합니다.
//Light Theme
val Grey50 = Color(0xFFF8F9FA)
val Grey900 = Color(0xFF202124)
val Grey700 = Color(0xFF5F6368)
val Green50 = Color(0xFFE6F4EA)
val Green100 = Color(0xFFCEEAD6)
  1. Theme.kt 파일을 열고 LightColorPalette를 아래 코드로 대체하여 슬롯에 색상을 추가합니다.
private val LightColorPalette = lightColors(
   background = Green100,
   surface = Green50,
   onSurface = Grey900,
   primary = Grey50,
   onPrimary = Grey900,
   secondary = Grey700
)

WoofTheme()darkTheme이 true로 설정되어 있는지 확인한 다음 false이면 MaterialTheme objectcolors를 밝은 색상 팔레트로 설정하고 true이면 어두운 색상 팔레트로 설정합니다.

@Composable
fun WoofTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {
   val colors = if (darkTheme) {
       DarkColorPalette
   } else {
       LightColorPalette
   }

   MaterialTheme(
       colors = colors,
       typography = Typography,
       shapes = Shapes,
       content = content
   )
}

앱에 색상 추가하기

색상을 추가했으니 이제 앱의 여러 영역에서 사용해 볼 차례입니다. 다음과 같은 슬롯을 사용합니다.

  • background: 목록의 배경색
  • surface: 목록 항목의 배경색(목록의 배경색과 구분되도록)
  • onSurface: 텍스트 색상(목록 항목 색상 위에서 가독성이 높아지도록)

나머지 두 개 색상은 Codelab의 뒷부분에서 사용합니다.

  1. MainActivity.kt를 엽니다. WoofApp()에서 LazyColumn에 배경 수정자를 추가하여 목록의 배경색으로 green을 적용합니다. 배경색을 Theme.kt에서 background로 설정한 색상으로 설정합니다. 앱 테마의 background 색상으로 설정한 색상에 MaterialTheme.colors.background를 통해 액세스할 수 있습니다.

Preview 탭에서 Build & Refresh를 클릭합니다.

import androidx.compose.material.MaterialTheme
import androidx.compose.foundation.background

LazyColumn(modifier =
   Modifier.background(MaterialTheme.colors.background))

수고하셨습니다. 이제 배경이 Green100이 되었습니다.

WoofPreview에 반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다. 이 앱에는 배경색이 적용되어 있습니다.

  1. DogItem()에서 Rowbackground() 확장을 추가하고 MaterialTheme.colors.surface를 전달합니다. 이렇게 하면 Row의 배경색이 앱 테마에 지정된 surface 색상을 사용하도록 설정됩니다.
import androidx.compose.ui.unit.dp

Row(
   modifier = Modifier
       .fillMaxWidth()
       .padding(8.dp)
       .background(MaterialTheme.colors.surface)
)

Preview 탭에서 이제 목록 항목에 앱의 배경색과 다른 색상이 적용되었고 각 목록 항목이 한층 구분되게 표시되는 것을 볼 수 있습니다.

DefaultPreview에 반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다. 이 앱에는 앱 배경색과 목록 항목 배경색이 적용되어 있습니다.

  1. DogInformation()에서 반려견 이름 텍스트 컴포저블과 반려견 나이 텍스트 컴포저블에 color를 추가합니다. 이렇게 하면 두 텍스트 컴포저블의 글꼴 색상이 변경됩니다. onSurface 색상을 사용합니다.
Column {
   Text(
       text = stringResource(dog.name),
       color = MaterialTheme.colors.onSurface,
       modifier = Modifier.padding(top = smallPadding)
   )
   Text(
       text = stringResource(R.string.years_old, dog.age.toString()),
       color = MaterialTheme.colors.onSurface
   )
}
  1. 앱을 Build & Refresh합니다. 강아지의 이름과 나이를 표시하는 텍스트가 배경과 대비되어 가독성이 높아졌으나, 밝은 테마에서는 어두운 테마에서만큼 그 차이가 확연하게 드러나지는 않습니다.

밝은 테마:

WoofPreview에 반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다. 이 앱에는 앱 배경색, 목록 항목 배경색과 텍스트 색상이 적용되어 있습니다.

아래에서 어두운 테마의 텍스트와 배경의 대비를 살펴보세요. 어두운 테마는 다음 섹션에서 구현합니다.

텍스트 색상이 적용되지 않은 어두운 테마

텍스트 색상이 적용된 어두운 테마

WoofPreview에 반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다. 이 앱에는 앱 배경색과 목록 항목 배경색이 적용되어 있습니다. 어두운 테마가 설정되어 있습니다.

WoofPreview에 반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다. 이 앱에는 앱 배경색, 목록 항목 배경색과 텍스트 색상이 적용되어 있습니다. 어두운 테마가 설정되어 있습니다.

어두운 테마

Android 시스템에서는 기기를 어두운 테마로 전환하는 옵션이 있습니다. 어두운 테마는 더 어둡고 부드러운 색상을 사용하며 아래와 같은 이점이 있습니다.

  • 전력 사용을 크게 줄일 수 있습니다(기기의 화면 기술에 따라 다름).
  • 시력이 낮은 사용자와 밝은 빛에 민감한 사용자를 위한 가시성을 개선합니다.
  • 조명이 어두운 환경에서 더 편하게 기기를 사용할 수 있습니다.

앱에 어두운 테마 강제 적용을 설정할 수 있습니다. 그러면 시스템이 어두운 테마를 구현합니다. 하지만 개발자가 직접 어두운 테마를 구현하면 앱 테마를 원하는 대로 관리하여 더 나은 사용자 환경을 제공할 수 있습니다.

직접 어두운 테마를 선택할 때는 어두운 테마의 색상은 접근성 대비 표준을 충족해야 한다는 사실에 유의하세요. 어두운 테마는 제한된 강조 색상과 함께 어두운 표면 색상을 사용합니다.

다음은 이 앱의 어두운 테마에 사용되는 색상입니다.

어두운 테마:

색상

이름

16진수 색상

슬롯

White 색상을 보여주는 이미지입니다.

White

#FFFFFF

primary

Grey100 색상을 보여주는 이미지입니다.

Grey100

#F1F3F4

onSurface

Grey100 색상을 보여주는 이미지입니다.

Grey100

#F1F3F4

onPrimary

Cyan700 색상을 보여주는 이미지입니다.

Cyan700

#129EAF

surface

Cyan900 색상을 보여주는 이미지입니다.

Cyan900

#007B83

background

Grey900 색상을 보여주는 이미지입니다.

Grey900

#202124

secondary

어두운 테마 추가하기

  1. Color.kt에서 어두운 테마 색상을 추가합니다. Grey900은 밝은 테마에 이미 추가했으므로 여기서는 4가지 색상만 추가합니다.
//Dark Theme
val White = Color(0xFFFFFFFF)
val Grey100 = Color(0xFFF1F3F4)
val Cyan900 = Color(0xFF007B83)
val Cyan700 = Color(0xFF129EAF)
  1. 기본적으로 제공된 색상은 더 이상 필요하지 않으므로 삭제합니다. 다음은 이 시점에서 파일에 포함되어 있는 값입니다.
//Light Theme
val Grey50 = Color(0xFFF8F9FA)
val Grey900 = Color(0xFF202124)
val Grey700 = Color(0xFF5F6368)
val Green50 = Color(0xFFE6F4EA)
val Green100 = Color(0xFFCEEAD6)

//Dark Theme
val White = Color(0xFFFFFFFF)
val Grey100 = Color(0xFFF1F3F4)
val Cyan900 = Color(0xFF007B83)
val Cyan700 = Color(0xFF129EAF)
  1. Theme.kt 파일에서 기존 DarkColorPalette를 아래의 색상으로 바꿉니다.
private val DarkColorPalette = darkColors(
   background = Cyan900,
   surface = Cyan700,
   onSurface = White,
   primary = Grey900,
   onPrimary = White,
   secondary = Grey100
)

미리보기에서 어두운 테마 보기

어두운 테마가 실제로 적용된 모습을 보려면 MainActivity.ktPreview()를 하나 더 추가합니다. 이렇게 하면 코드에서 UI 레이아웃을 변경한 경우 밝은 테마와 어두운 테마를 동시에 미리 볼 수 있습니다.

  1. DefaultPreview() 아래에 DarkThemePreview()라는 새 함수를 만들고 @Preview@Composable 주석을 추가합니다.
@Preview
@Composable
fun DarkThemePreview() {

}
  1. DarkThemePreview() 안에 WoofTheme()을 추가합니다. WoofTheme()을 추가하지 않으면 앱에 추가한 스타일을 볼 수 없습니다. darkTheme 매개변수를 true로 설정합니다.
@Preview
@Composable
fun DarkThemePreview() {
   WoofTheme(darkTheme = true) {

   }
}
  1. WoofTheme() 안에서 WoofApp()을 호출합니다.
@Preview
@Composable
fun DarkThemePreview() {
   WoofTheme(darkTheme = true) {
       WoofApp()
   }
}

이제 Preview 섹션에서 Build & Refresh를 클릭하고 아래로 스크롤하면 앱이 어두운 앱/목록 항목 배경과 흰색 텍스트를 포함하여 어두운 테마로 표시되는 것을 볼 수 있습니다. 어두운 테마와 밝은 테마의 차이를 비교해 보세요.

어두운 테마

밝은 테마

WoofPreview에 반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다. 이 앱에는 앱 배경색, 목록 항목 배경색과 텍스트 색상이 적용되어 있습니다. 어두운 테마가 설정되어 있습니다.

WoofPreview에 반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다. 이 앱에는 앱 배경색, 목록 항목 배경색과 텍스트 색상이 적용되어 있습니다.

기기 또는 에뮬레이터에서 어두운 테마 보기

에뮬레이터나 실제 기기에서 앱을 어두운 테마로 보려면 다음 단계를 따르세요.

  1. 기기에서 설정 앱으로 이동합니다.
  2. 어두운 테마를 검색하여 클릭합니다.
  3. 어두운 테마를 사용 설정합니다.
  4. Woof 앱을 다시 열면 앱이 어두운 테마로 표시됩니다.

반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다. 이 앱에는 앱 배경색, 목록 항목 배경색과 텍스트 색상이 적용되어 있습니다. 어두운 테마가 설정되어 있습니다.

이 Codelab은 주로 밝은 테마를 중심으로 진행되니 다음으로 넘어가기 전에 어두운 테마를 사용 중지하세요.

  1. 기기에서 설정 앱으로 이동합니다.
  2. 디스플레이를 선택합니다.
  3. 어두운 테마를 사용 중지합니다.

이 섹션을 시작할 때와 지금 앱이 어떻게 다르게 표시되는지 비교해 보세요. 목록 항목과 텍스트가 더 또렷하게 표시되고 보다 매력적인 색 구성이 적용되었습니다.

색상 없음

색상 적용됨(밝은 테마)

색상 적용됨(어두운 테마)

반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다.

DefaultPreview에 반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다. 이 앱에는 앱 배경색, 목록 항목 배경색과 텍스트 색상이 적용되어 있습니다.

반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다. 이 앱에는 앱 배경색, 목록 항목 배경색과 텍스트 색상이 적용되어 있습니다. 어두운 테마가 설정되어 있습니다.

5. 도형 추가

앱의 모든 도형은 기본적으로 직사각형입니다. 다른 도형을 적용하면 컴포저블의 디자인과 분위기가 크게 달라질 수 있습니다. 도형은 주의를 집중시키고, 구성요소를 구분하고, 상태를 전달하고, 브랜드를 표현합니다.

많은 도형이 모서리가 둥근 직사각형을 나타내는 RoundedCornerShape를 사용하여 정의됩니다. 전달되는 숫자는 모서리의 둥근 정도를 정의합니다. RoundedCornerShape(percent = 0)을 사용하면 직사각형의 모서리가 각이 지고, RoundedCornerShape(percent = 50)을 사용하면 모서리가 완전히 둥급니다. 더 복잡한 도형으로 테스트해 보려면 Material 사이트의 도형 맞춤설정 도구를 사용하세요..

0퍼센트

25퍼센트

50퍼센트

0퍼센트 RoundedCornerShape를 보여주는 이미지입니다.

25퍼센트 RoundedCornerShape를 보여주는 이미지입니다.

50퍼센트 RoundedCornerShape를 보여주는 이미지입니다.

Shape.kt 파일은 Compose에서 구성요소의 도형을 정의하는 데 사용됩니다. 구성요소에는 소형, 중형, 대형의 세 가지 유형이 있습니다. 이 섹션에서는 medium 크기로 정의된 Card 구성요소를 수정합니다. 구성요소는 크기를 기준으로 여러 도형 카테고리로 그룹화됩니다.

Image는 구성요소가 아니므로 MainActivity.kt에서 Image의 도형을 추가합니다.

이 섹션에서는 반려견의 이미지를 원형으로 만들고 목록 항목의 도형을 수정합니다.

반려견 이미지를 원형으로 만들기

  1. 먼저 반려견 사진 아이콘을 원형으로 수정합니다. MainActivity.kt를 엽니다. DogIcon()에서 Imagemodifierclip 속성을 추가합니다. 이렇게 하면 이미지가 도형으로 잘립니다. RoundedCornerShape()를 전달하고 50을 전달하여 모서리를 완전히 둥글게 만듭니다.
import androidx.compose.ui.draw.clip
import androidx.compose.foundation.shape.RoundedCornerShape

@Composable
fun DogIcon(@DrawableRes dogIcon: Int, modifier: Modifier = Modifier) {
   Image(
       modifier = modifier
           .size(64.dp)
           .padding(8.dp)
           .clip(RoundedCornerShape(50)),

DefaultPreview를 보면 반려견 아이콘이 원인 것을 볼 수 있습니다. 하지만 측면이 잘려서 완전히 원형으로 표시되지 않은 사진도 있습니다.

반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다. 이 앱에는 맞춤 색상이 적용되어 있고 반려견 사진이 원형입니다.

  1. 모든 사진을 원형으로 만들려면 ContentScaleCrop 속성을 추가합니다. 이렇게 하면 이미지가 도형에 맞게 잘립니다. contentScalemodifier의 일부가 아니라 Image의 속성입니다.
import androidx.compose.ui.layout.ContentScale

@Composable
fun DogIcon(dogIcon: Int, modifier: Modifier = Modifier) {
   Image(
       modifier = modifier
           .size(64.dp)
           .padding(8.dp)
           .clip(RoundedCornerShape(50)),
       contentScale = ContentScale.Crop,

이제 앱을 실행하면 아이콘이 원형으로 표시됩니다.

반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다. 이 앱에는 맞춤 색상이 적용되어 있고 반려견 사진이 원형입니다.

목록 항목에 도형 추가하기

이 섹션에서는 목록 항목에 도형을 추가합니다. 목록 항목은 이미 Row에 표시되지만, Row에는 도형을 지정하는 기능이 없습니다. 대신 CardRow를 추가합니다. Card는 단일 컴포저블을 포함할 수 있고 장식 옵션을 포함하는 표면입니다. 장식은 테두리, 도형, 도형, 고도 등을 통해 추가할 수 있습니다. 이 섹션에서는 Card를 사용하여 목록 항목에 도형을 추가합니다.

  1. DogItem()에서 Row를 감싸는 Card를 추가합니다.
import androidx.compose.material.Card

@Composable
fun DogItem(dog: Dog, modifier: Modifier = Modifier) {
   Card() {
       Row(
  1. Shape.kt 파일을 엽니다. Card는 중형 구성요소이므로 Shapes 객체의 medium 속성을 업데이트합니다. 이 앱에서는 목록의 모서리를 둥글게 만들되 완전히 원형으로 만들지는 않으려고 합니다. 이렇게 하려면 medium 속성에 16.dp를 전달합니다.
val Shapes = Shapes(
   small = RoundedCornerShape(4.dp),
   medium = RoundedCornerShape(16.dp),
   large = RoundedCornerShape(0.dp)
)
  1. Card는 기본적으로 이미 중형 도형을 사용하고 있기 때문에 명시적으로 중형 도형으로 설정할 필요가 없습니다. Preview를 새로고침하면 둥근 모서리를 볼 수 있습니다. 그런데 목록 항목 사이에 패딩이 없어서 한 목록 항목의 끝과 다음 목록 항목의 시작이 명확히 구분되지 않습니다. 이제 목록 항목 사이에 패딩을 추가하여 각 항목을 구분해 보겠습니다.

반려견의 이름, 사진, 나이 목록이 표시된 미리보기를 보여주는 이미지입니다. 이 앱에는 맞춤 색상이 적용되어 있고 목록 항목의 모서리가 둥급니다.

WoofTheme()Theme.kt 파일로 돌아가서 MaterialTheme()을 살펴보면 shapes 속성이 방금 업데이트한 Shapes val로 설정된 것을 볼 수 있습니다.

MaterialTheme(
   colors = colors,
   typography = Typography,
   shapes = Shapes,
   content = content
)

수정자를 업데이트하고 패딩 추가하기

  1. 이제 CardDogItem()에 표시되는 첫 번째 컴포저블이 되었으므로 DogItem 컴포저블에 전달된 수정자는 Row가 아닌 Card에 전달되어야 합니다. 이제 RowModifier의 새 인스턴스를 사용합니다.
@Composable
fun DogItem(dog: Dog, modifier: Modifier = Modifier) {
   Card(
       modifier = modifier
   ) {
       Row(
           modifier = Modifier
               .fillMaxWidth()
               .padding(8.dp)
               .background(MaterialTheme.colors.surface)
       )
  1. Card modifierpadding을 추가하고 8.dp를 전달하여 각 목록 항목 주위에 패딩을 추가합니다.
Card(
   modifier = modifier.padding(8.dp)
)

이제 Preview를 새로고침하면 각 항목 사이에 추가된 패딩으로 인해 목록 항목의 모서리가 둥근 것을 더 명확하게 볼 수 있습니다.

반려견의 이름, 사진, 나이 목록이 표시된 미리보기를 보여주는 이미지입니다. 이 앱에는 맞춤 색상이 적용되어 있고 목록 항목의 모서리가 둥급니다.

비명시적 색상

CardSurface입니다. Theme.kt 파일에는 surface 슬롯에 명시적으로 설정된 색상이 있습니다. 따라서 Rowsurface 색을 명시적으로 삭제할 필요가 없으므로 색상을 삭제해도 됩니다.

  1. DogItem()에서 배경색의 명시적 설정을 삭제합니다.
Row(
   modifier = Modifier
       .fillMaxWidth()
       .padding(8.dp)
)

Preview를 새로고침하면 명시적 색상 할당을 삭제했는데도 Row에 동일한 배경색이 적용된 것을 볼 수 있습니다.

반려견의 이름, 사진, 나이 목록이 표시된 미리보기를 보여주는 이미지입니다. 이 앱에는 맞춤 색상이 적용되어 있고 목록 항목의 모서리가 둥급니다.

  1. 반려견의 이름과 나이 TextSurface 위에 있으므로 기본적으로 onSurface 색상이 적용됩니다. DogInformation()에서 두 Text 항목의 명시적 색상 설정을 삭제합니다.

이 컴포저블은 이제 다음과 같습니다.

@Composable
fun DogInformation(@StringRes dogName: Int, dogAge: Int, modifier: Modifier = Modifier) {
   Column {
       Text(
           text = stringResource(dogName),
           modifier = modifier.padding(top = 8.dp)
       )
       Text(
           text = stringResource(R.string.years_old, dogAge)
       )
   }
}

목록 항목의 고도 추가하기

목록 항목 도형을 적용하니 앱이 근사해졌습니다. 이번에는 목록 항목이 배경과 더 대비되도록 몇 가지 요소를 추가해 보겠습니다. 앞에서 Card shape 속성을 사용하여 목록 항목에 도형을 적용했습니다. 이번에는 Card elevation 속성을 사용하여 카드에 고도를 추가하겠습니다. 고도는 그림자를 추가하여 앱이 더 사실적이고 매력적으로 보이도록 Card와 배경 간의 대비를 적용합니다.

  1. DogItem()에서 list_item_elevationCardelevation 속성으로 추가합니다.
Card(
   modifier = Modifier.padding(8.dp),
   elevation = 4.dp
)
  1. Preview를 새로고칩니다. 고도로 인해 앱에 그림자와 깊이가 더해져서 더 사실적으로 보입니다.

반려견의 이름, 사진, 나이 목록이 표시된 미리보기를 보여주는 이미지입니다. 이 앱에는 맞춤 색상이 적용되어 있고 목록 항목의 모서리가 둥글며 배경과 목록 항목 사이에 고도가 적용되었습니다.

다음은 도형을 적용한 전후의 앱을 나란히 비교한 이미지입니다. 도형을 추가한 결과 앱이 얼마나 더 근사해졌는지 살펴보세요.

도형 없음

도형 적용됨

DefaultPreview에 반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다. 이 앱에는 앱 배경색, 목록 항목 배경색과 텍스트 색상이 적용되어 있습니다.

반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다. 이 앱에는 맞춤 색상과 도형이 적용되어 있습니다.

6. 서체 추가

Material Design 서체 스케일

서체 스케일은 유연하면서도 일관된 스타일을 위해 앱 전반에서 사용할 수 있는 글꼴 스타일 모음입니다. Material Design 서체 스케일에는 서체 시스템에서 지원하는 13가지 글꼴 스타일이 있습니다. 이러한 옵션은 앱을 맞춤설정하려는 경우에만 사용하면 됩니다. 각 서체 스케일 카테고리에 무엇을 설정해야 할지 잘 모르겠다면 기본 서체 스케일을 사용해 보세요.

서체 시스템에서 지원하는 열세 가지 스타일을 보여주는 서체 스케일 이미지입니다.

서체 스케일에는 각각 의도된 응용 방법과 의미를 갖는 재사용 가능한 텍스트 카테고리가 있습니다. 이 앱에서는 헤드라인 카테고리와 본문 카테고리만 사용합니다.

헤드라인

서체 스케일에는 헤드라인 1~6이 있습니다. 헤드라인은 화면에서 가장 큰 텍스트로, 짧고 중요한 텍스트 또는 숫자에 사용됩니다.

본문

본문 텍스트에는 1~2가 있고, 작은 텍스트 크기에 적합하기 때문에 주로 긴 글에 사용됩니다.

글꼴

Android 플랫폼에서는 몇 가지 글꼴을 제공하지만 기본적으로 제공되지 않는 글꼴을 사용하여 맞춤설정할 수 있습니다. 맞춤 글꼴은 직접 추가하여 브랜딩용으로 사용할 수 있습니다.

이 섹션에서는 Abril Fatface, Montserrat Bold, Montserrat Regular 맞춤 글꼴을 추가합니다. Material 서체 시스템의 H1 및 H2 헤드라인과 body1 텍스트를 사용하고, 앱에 이러한 텍스트를 추가합니다.

글꼴 Android 리소스 디렉터리 만들기

앱에 글꼴을 추가하려면 먼저 글꼴 디렉터리를 추가해야 합니다.

  1. Android 스튜디오의 프로젝트 뷰에서 res 폴더를 마우스 오른쪽 버튼으로 클릭합니다.
  2. New > Android Resource Directory를 선택합니다.

파일 구조에서 Android 리소스 디렉터리를 찾는 모습을 보여주는 이미지입니다.

  1. 디렉터리 이름을 font로 지정하고 리소스 유형을 font로 설정한 후 OK를 클릭합니다.

New Resource Directory에서 font 디렉터리를 추가하는 모습을 보여주는 이미지입니다.

  1. res > drawable > font에 있는 새 글꼴 리소스 디렉터리를 엽니다.

맞춤 글꼴 다운로드하기

Android 플랫폼에서 제공하지 않는 글꼴을 사용하려고 하므로 맞춤 글꼴을 다운로드해야 합니다.

  1. https://fonts.google.com/으로 이동합니다.
  2. Montserrat을 검색하고 Download family를 클릭합니다.
  3. zip 파일의 압축을 풉니다.
  4. 다운로드한 Montserrat 폴더를 엽니다. static 폴더에서 Montserrat-Bold.ttfMontserrat-Regular.ttf를 찾습니다(ttf는 TrueType Font의 약자로, 글꼴 파일의 형식입니다). 두 글꼴을 선택하고 Android 스튜디오의 프로젝트 글꼴 리소스 디렉터리로 드래그합니다.

Montserrat 글꼴의 ststic 폴더의 콘텐츠를 보여주는 이미지입니다.

  1. 글꼴 폴더에서 Montserrat-Bold.ttfmontserrat_bold.ttf로 변경하고 Montserrat-Regular.ttfmontserrat_regular.ttf로 변경합니다.
  2. Abril Fatface를 검색하고 Download family를 클릭합니다.
  3. 다운로드한 Abril_Fatface 폴더를 엽니다. AbrilFatface-Regular.ttf를 선택하고 글꼴 리소스 디렉터리로 드래그합니다.
  4. 글꼴 폴더에서 Abril_Fatface.ttfabril_fatface_regular.ttf로 변경합니다.

세 개의 맞춤 글꼴 파일이 있는 프로젝트의 글꼴 리소스 디렉터리는 다음과 같습니다.

글꼴 폴더에 추가된 글꼴 파일을 보여주는 이미지입니다.

글꼴 초기화하기

  1. 프로젝트 창에서 ui.theme > Type.kt를 열고 Typography 변수의 콘텐츠를 삭제합니다.
// Set of Material typography styles to start with
val Typography = Typography(

)
  1. import 문 아래, Typography val 위에서 다운로드한 글꼴을 초기화합니다. 먼저 Abril FatfaceFontFamily와 동일하게 설정하고 글꼴 파일 abril_fatface_regular와 함께 Font를 전달하여 초기화합니다.
val AbrilFatface = FontFamily(
   Font(R.font.abril_fatface_regular)
)
  1. Abril Fatface 아래의 MontserratFontFamily와 동일하게 설정하고 글꼴 파일 montserrat_regular와 함께 Font를 전달하여 초기화합니다. montserrat_bold의 경우 FontWeight.Bold도 포함합니다. 글꼴 파일의 굵은 버전도 전달하긴 하지만, Compose는 이 파일이 굵은 버전이라는 사실을 알지 못하므로 파일을 FontWeight.Bold에 명시적으로 연결해야 합니다.
val AbrilFatface = FontFamily(
   Font(R.font.abril_fatface_regular)
)

val Montserrat = FontFamily(
   Font(R.font.montserrat_regular),
   Font(R.font.montserrat_bold, FontWeight.Bold)
)

다음으로, 방금 추가한 글꼴에 다양한 유형의 헤드라인을 설정합니다. Typography 객체에는 위에서 설명한 13가지 서체를 위한 매개변수가 있습니다. 매개변수는 원하는 개수만큼 정의할 수 있습니다. 이 앱에서는 h1(헤드라인 1), h2(헤드라인 2), body1을 설정합니다. 이 앱의 다음 부분에서 사용할 h3(헤드라인 3)도 여기에 추가합니다.

다음은 추가한 각 헤드라인의 글꼴과 크기를 보여주는 앱 개요 섹션의 표입니다.

제목

글꼴

글꼴 두께

크기

h1

AbrilFatface 글꼴을 보여주는 이미지입니다.

Normal

30sp

h2

Montserrat 글꼴을 보여주는 이미지입니다.

Bold

20sp

h3

Montserrat 글꼴을 보여주는 이미지입니다.

Bold

14sp

body1

Montserrat 글꼴을 보여주는 이미지입니다.

Normal

14sp

  1. 위 표를 사용하여 Typography val을 입력합니다. h1 속성은 TextStyle과 동일하게 설정하고 fontFamily, fontWeight, fontSize에 위 표의 정보로 입력합니다. 즉, h1로 설정된 모든 텍스트에는 일반 글꼴 두께와 fontSize 30.spAbril Faface가 적용됩니다.

h2, h3, body1에도 이 프로세스를 반복합니다.

val Typography = Typography(
   h1 = TextStyle(
       fontFamily = AbrilFatface,
       fontWeight = FontWeight.Normal,
       fontSize = 30.sp
   ),
   h2 = TextStyle(
       fontFamily = Montserrat,
       fontWeight = FontWeight.Bold,
       fontSize = 20.sp
   ),
   h3 = TextStyle(
       fontFamily = Montserrat,
       fontWeight = FontWeight.Bold,
       fontSize = 14.sp
   ),
   body1 = TextStyle(
       fontFamily = Montserrat,
       fontWeight = FontWeight.Normal,
       fontSize = 14.sp
   )
)

WoofTheme()Theme.kt 파일로 돌아가서 MaterialTheme()을 살펴보면 typography 속성이 방금 업데이트한 Typography val로 설정된 것을 볼 수 있습니다.

MaterialTheme(
   colors = colors,
   typography = Typography,
   shapes = Shapes,
   content = content
)

앱 텍스트에 서체 추가하기

이번에는 앱의 각 텍스트 인스턴스에 헤드라인 추가합니다.

  1. dog name은 짧고 중요한 정보이므로 스타일로 h2(헤드라인 2)를 추가합니다. dog age에는 작은 텍스트 크기가 어울리므로 스타일로 body1을 추가합니다.
@Composable
fun DogInformation(@StringRes dogName: Int, dogAge: Int, modifier: Modifier = Modifier) {
   Column {
       Text(
           text = stringResource(dogName),
           style = MaterialTheme.typography.h2,
           modifier = modifier.padding(top = 8.dp)
       )
       Text(
           text = stringResource(R.string.years_old, dogAge),
           style = MaterialTheme.typography.body1
       )
   }
}
  1. 앱을 새로고침하면 반려견 이름이 굵은 20.sp Montserrat 글꼴로, 반려견 나이가 일반 14.sp Montserrat 글꼴로 표시되는 것을 볼 수 있습니다.

반려견의 이름, 사진, 나이 목록이 표시된 미리보기를 보여주는 이미지입니다. 이 앱에는 맞춤 색상, 도형, 서체가 적용되어 있습니다.

다음은 서체를 추가한 전후의 앱을 나란히 비교한 이미지입니다. 반려견 이름과 반려견 나이의 글꼴 차이를 살펴보세요.

서체 없음

서체가 적용됨

반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다. 이 앱에는 맞춤 색상과 도형이 적용되어 있습니다.

반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다. 이 앱에는 맞춤 색상, 도형, 서체가 적용되어 있습니다.

7. 상단 바 추가

Scaffold는 다양한 구성요소와 화면 요소(Image, Row, Column)의 슬롯을 제공하는 레이아웃입니다. Scaffold는 이 섹션에서 사용할 topBar의 슬롯도 제공합니다.

topBar는 여러 용도로 사용할 수 있지만, 여기서는 앱에 브랜딩과 개성을 적용하는 용도로 사용합니다. 아래의 스크린샷과 같은 컴포저블을 만든 다음 ScaffoldtopBar 섹션에 배치합니다.

이미지와 텍스트로 이루어진 Woof 상단 바를 보여주는 이미지입니다.

이 앱의 상단 바는 로고와 앱 제목이 있는 하나의 행으로 구성됩니다. 로고에는 귀여운 그라데이션 강아지 발과 앱의 이름이 적용되어 있습니다.

이미지와 텍스트로 이루어진 하나의 행으로 구성된 상단 바를 보여주는 이미지입니다.

상단 바에 이미지와 텍스트 추가하기

  1. MainActivity.kt에서 modifier를 받는 WoofTopAppBar()라는 컴포저블을 만듭니다.
@Composable
fun WoofTopAppBar(modifier: Modifier = Modifier) {

}
  1. WoofTopAppBar() 안에 Row()를 추가합니다.
@Composable
fun WoofTopAppBar(modifier: Modifier = Modifier) {
   Row() {

   }
}
  1. RowImage를 추가합니다. painter를 사용하여 Image를 드로어블 폴더의 ic_woof_logo로 설정하고, contentDescriptionnull로 설정합니다. 이때 앱 로고는 시각 장애가 있는 사용자를 위한 의미 정보를 제공하지 않으므로 콘텐츠 설명을 추가할 필요가 없습니다.
Image(
   painter = painterResource(R.drawable.ic_woof_logo),
   contentDescription = null
)
  1. 다음으로, Image 뒤에 Row 안에 Text 컴포저블을 추가하고 stringResource()를 사용하여 app_name의 값으로 설정합니다. 그러면 텍스트가 strings.xml에 저장된 앱 이름으로 설정됩니다.
Text(
   text = stringResource(R.string.app_name)
)
  1. TopAppBar()에 아이콘과 앱 이름을 추가했으니 이번에는 레이아웃에 TopAppBar()를 추가해야 합니다. WoofApp()에서 LazyColumn을 감싸는 Scaffold를 추가합니다.
import androidx.compose.material.Scaffold

@Composable
fun WoofApp() {
   Scaffold(

   ) {
       LazyColumn(modifier =
        Modifier.background(MaterialTheme.colors.background)) {
           items(dogs) {
               DogItem(dog = it)
           }
       }
   }
}
  1. Scaffold 안에서 topBar 속성을 추가하고 WoofTopAppBar()로 설정합니다.
Scaffold(
   topBar = {
       WoofTopAppBar()
   }
)

WoofApp() 컴포저블은 이제 다음과 같습니다.

@Composable
fun WoofApp() {
   Scaffold(
       topBar = {
           WoofTopAppBar()
       }
   ) {
       LazyColumn(modifier = Modifier.background(MaterialTheme.colors.background)) {
           items(dogs) {
               DogItem(dog = it)
           }
       }
   }
}
  1. Preview를 새로고침하고 상단 앱 바를 살펴봅니다. 아이콘과 텍스트가 표시되지만, 우리가 원하는 완성된 모습은 아닙니다. 다음 섹션에서는 색상, 서체, 패딩 등을 사용하여 앱을 더 멋지게 디자인합니다.

이미지와 텍스트로 이루어진 상단 바가 있는 Woof 앱을 보여주는 이미지입니다.

상단 바에 디자인 적용하기

  1. 먼저 상단 바가 나머지 부분과 구분되도록 배경색을 추가합니다. WoofTopAppBar()에서 Rowmodifier를 추가하고 배경색을 primary로 설정하여 배경색으로 primary 앱 테마 색상을 추가합니다.
Row(
   modifier = modifier
       .background(color = MaterialTheme.colors.primary)
){ }

이미지와 텍스트로 이루어진 상단 바에 배경색이 부분적으로 적용된 Woof 앱을 보여주는 이미지입니다.

  1. 배경색이 아이콘과 텍스트 뒤에만 표시되는 것을 볼 수 있습니다. 앱의 전체 너비에 적용되도록 하려면 RowmodifierfillMaxWidth()로 설정합니다.
Row(
   modifier = modifier
       .fillMaxWidth()
       .background(color = MaterialTheme.colors.primary)
){ }

이미지와 텍스트로 이루어진 상단 바에 배경색이 전체적으로 적용된 Woof 앱을 보여주는 이미지입니다.

  1. 다음으로, 앞에서 정의한 h1(헤드라인 1) 스타일을 따르도록 텍스트를 업데이트합니다. 배경이 primary 색상으로 설정되어 있으므로 텍스트가 자동으로 onPrimary 색상으로 설정됩니다.
Text(
   text = stringResource(R.string.app_name),
   style = MaterialTheme.typography.h1
)
  1. 조금 나아지긴 했지만, 이미지가 여전히 너무 작습니다. 이미지 주변에 패딩을 추가하면 좋겠네요. Image에 수정자를 추가하고, 이미지 크기를 R.dimen.image_size로 설정하고, 이미지 주위의 패딩을 R.dimen.padding_small로 설정합니다.
Image(
   modifier = Modifier
       .size(64.dp)
       .padding(8.dp),
   painter = painterResource(R.drawable.ic_woof_logo),
   contentDescription = null
)

이미지와 텍스트로 이루어진 상단 바에 흰색 배경색이 적용된 Woof 앱을 보여주는 이미지입니다. 텍스트 스타일은 h1이고, 이미지 주위에 패딩이 있습니다.

  1. 거의 완료되었습니다. 이제 세로 정렬을 Alignment.CenterVertically로 설정하면 행에 있는 모든 항목이 세로 방향으로 가운데에 배치됩니다.
import androidx.compose.ui.Alignment

Row(
   modifier = modifier
       .fillMaxWidth()
       .background(color = MaterialTheme.colors.primary),
   verticalAlignment = Alignment.CenterVertically
){ }

이미지와 텍스트로 이루어진 상단 바에 흰색 배경색이 적용된 Woof 앱을 보여주는 이미지입니다. 텍스트 스타일은 h1이고, 이미지 주위에 패딩이 있으며, 모든 항목이 세로 방향으로 가운데에 배치되어 있습니다.

앱을 실행하고 TopAppBar가 앱의 통일성을 얼마나 높여주는지 살펴보세요.

상단 앱 바 없음

상단 앱 바가 적용됨

반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다. 이 앱에는 맞춤 색상, 도형, 서체가 적용되어 있습니다.

반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다. 이 앱에는 맞춤 색상, 도형, 서체가 적용되어 있고 상단 바가 있습니다.

이제 앱을 어두운 테마로 실행합니다. 상단 바는 primary 색상을 사용하고 텍스트는 onSurface 색상을 사용하므로 어두운 테마를 적용하기 위해 아무것도 업데이트할 필요가 없습니다.

반려견의 이름, 사진, 나이 목록이 표시된 앱을 보여주는 이미지입니다. 이 앱에는 맞춤 색상, 도형, 서체가 적용되어 있고 상단 바가 있습니다. 어두운 모드로 표시되어 있습니다.

축하합니다. Codelab을 완료했습니다.

8. [선택사항] 상태 표시줄 변경

사용자에게 보다 통일된 환경을 제공하려면 시간, 인터넷 연결, 배터리 상태와 같은 정보가 안내되는 상태 표시줄의 색상을 업데이트할 수 있습니다.

상태 표시줄을 둘러싼 상자가 표시된 Woof 앱을 보여주는 이미지입니다.

  1. app > res > values > colors.xml로 이동합니다.
  2. <resources> 태그의 콘텐츠를 삭제합니다.
<resources>

</resources>
  1. 밝은 테마 상태 표시줄을 위해 grey_50을 추가하고 #FFF8F9FA로 설정합니다. 어두운 테마 상태 표시줄을 위해 grey_900을 추가하고 #FF202124로 설정합니다.
<resources>
   <color name="grey_50">#FFF8F9FA</color>
   <color name="grey_900">#FF202124</color>
</resources>
  1. app > res > values > themes.xml로 이동하여 android:statusBarColor의 색상을 grey_50으로 바꿉니다.
<resources>
   <style name="Theme.Woof" parent="android:Theme.Material.Light.NoActionBar">
       <item name="android:statusBarColor">@color/grey_50</item>
   </style>
</resources>
  1. 기기 또는 에뮬레이터에서 앱을 실행합니다.

밝은 테마의 맞춤 상태 표시줄이 있는 Woof 앱을 보여주는 이미지입니다.

이제 상태 표시줄에 상단 앱 바와 동일한 색상이 적용되어 보다 일관된 색 구성이 구현되었지만, 이렇게 하니 아이콘을 보기가 어렵습니다.

  1. themes.xml 파일에서 statusBarColor 아래에 windowLightStatusBar를 추가하고 true로 설정합니다.
<resources>
   <style name="Theme.Woof" parent="android:Theme.Material.Light.NoActionBar">
       <item name="android:statusBarColor">@color/grey_50</item>
       <item name="android:windowLightStatusBar">true</item>
   </style>
</resources>
  1. 오류 메시지가 표시됩니다. 메시지 위에 마우스를 가져간 다음 Override Resources in values-v23을 누릅니다.

Android 스튜디오에서 오류 팝업 이미지입니다.

  1. 그러면 v23/themes.xml이라는 새로운 themes.xml 파일이 생성됩니다. 이 파일은 API 레벨 23 및 이후 버전에서 사용됩니다.
  2. 에뮬레이터에서 앱을 실행합니다. 이제 아이콘을 볼 수 있습니다.

밝은 테마의 맞춤 상태 표시줄이 있는 Woof 앱을 보여주는 이미지입니다.

어두운 테마에 상태 표시줄 추가하기

이번에는 어두운 테마의 상태 표시줄을 맞춤설정합니다.

  1. res 폴더에 values-night이라는 새 Android 리소스 디렉터리를 추가합니다.

cdc98bf466706a30.png

  1. Project Source Files 파일 뷰로 전환합니다.

Project Source File 뷰가 선택된 모습을 보여주는 이미지입니다.

  1. app > src > main > res > values-night로 이동합니다.
  2. values-night 안에 themes.xml이라는 Values Resource File을 추가합니다.
  3. 이름이 Theme.Woof이고 상위 요소가 android:style/Theme.Material.NoActionBar인 스타일 태그를 추가합니다.
<resources>
   <style name="Theme.Woof" parent="android:style/Theme.Material.NoActionBar">

   </style>
</resources>
  1. 상태 표시줄 색상을 grey_900으로 추가합니다. 기본값은 흰색 아이콘이므로 windowsStatusLightBar는 추가하지 않아도 됩니다.
<resources>
   <style name="Theme.Woof" parent="android:style/Theme.Material.NoActionBar">
       <item name="android:statusBarColor">@color/grey_900</item>
   </style>
</resources>
  1. 앱을 어두운 테마로 실행하여 업데이트된 상태 표시줄을 봅니다.

어두운 테마의 맞춤 상태 표시줄이 있는 Woof 앱을 보여주는 이미지입니다.

9. 솔루션 코드 가져오기

완료된 Codelab의 코드를 다운로드하려면 이 git 명령어를 사용하면 됩니다.

$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-woof.git
$ cd basic-android-kotlin-compose-training-woof
$ git checkout material

또는, ZIP 파일로 저장소를 다운로드한 다음 압축을 풀고 Android 스튜디오에서 열어도 됩니다.

솔루션 코드를 보려면 GitHub에서 확인하세요.

10. 결론

이렇게 해서 첫 번째 Material 앱을 만들었습니다! 밝은 테마와 어두운 테마의 맞춤 색상 팔레트를 추가하고, 여러 구성요소의 도형을 만들고, 글꼴을 다운로드하여 앱에 추가하고, 이 모든 요소를 연동해주는 멋진 상단 바를 만들었습니다. 이 Codelab에서 배운 내용을 활용하여 새로 만드는 앱의 색상, 도형, 서체를 원하는 대로 변경해 보세요!

요약

  • Material Theming을 사용하면 색상, 서체, 도형 맞춤설정에 관한 안내에 따라 앱에서 Material Design을 사용할 수 있습니다.
  • Theme.kt 파일에는 [앱 이름]+Theme()(이 앱의 경우 WoofTheme())라는 이름의 컴포저블을 통해 테마가 정의됩니다. 이 컴포저블의 MaterialTheme 객체가 앱의 color, typography, shapes, content를 설정합니다.
  • Colors.kt에는 앱에서 사용하는 색상을 나열합니다. 그런 다음 Theme.kt에서 LightColorPaletteDarkColorPalette의 색상을 특정 슬롯에 할당합니다. 모든 슬롯을 할당할 필요는 없습니다.
  • 앱에 어두운 테마 강제 적용을 설정할 수 있습니다. 그러면 시스템이 어두운 테마를 구현합니다. 하지만 개발자가 직접 어두운 테마를 구현하면 앱 테마를 원하는 대로 관리하여 더 나은 사용자 환경을 제공할 수 있습니다.
  • Shapes.kt에서는 앱의 도형을 정의합니다. 도형에는 세 가지 크기(소형, 중형, 대형)가 있습니다. 도형 모서리를 얼마나 둥글게 만들지 지정할 수 있습니다.
  • 도형은 주의를 집중시키고, 구성요소를 구분하고, 상태를 전달하고, 브랜드를 표현합니다.
  • Types.kt에서는 글꼴을 초기화하고 Material Design 서체 스케일의 fontFamily, fontWeight, fontSize를 할당합니다.
  • Material Design 서체 스케일에는 앱과 앱 콘텐츠의 요구 사항을 지원하는 다양한 스타일이 있습니다. 서체 스케일은 서체 시스템에서 지원하는 13가지 스타일로 구성됩니다.

11. 자세히 알아보기