Jetpack Compose でのマテリアル テーマ設定

1. 始める前に

マテリアル デザインは Google のデザイナーとデベロッパーが設計、サポートするデザイン システムで、Android やその他のモバイル プラットフォーム、ウェブ プラットフォームで、高品質なデジタル エクスペリエンスを実現します。見やすく魅力的なアプリの UI を一貫したデザインで作成するためのガイドラインとして利用できます。

この Codelab では、アプリでマテリアル デザインを使用するためのマテリアル テーマ設定と、色、タイポグラフィ、シェイプのカスタマイズについて学習します。アプリは必要に応じて少しだけでも大きくでもカスタマイズできます。また、トップ アプリバーを追加してアプリの名前やアイコンを表示する方法もわかります。

前提条件

  • Kotlin 言語(構文、関数、変数など)に精通している。
  • パディングのある行と列を含め、Compose でレイアウトを作成できる。
  • Compose で簡単なリストを作成できる。

学習内容

  • Compose アプリにマテリアル テーマ設定を適用する方法
  • アプリにカスタム カラーパレットを追加する方法
  • アプリにカスタム フォントを追加する方法
  • アプリ内の要素にカスタム シェイプを追加する方法
  • アプリにトップ アプリバーを追加する方法

作成するアプリの概要

  • マテリアル デザインのベスト プラクティスを取り入れた、洗練されたアプリを作成します。

必要なもの

  • Android Studio の最新バージョン
  • スターター コードとフォントをダウンロードするためのインターネット接続

2. アプリの概要

この Codelab では、犬のリストを表示するアプリ、Woof を作成します。Woof ではマテリアル デザインを使用して洗練されたアプリ エクスペリエンスを実現します。

92eca92f64b029cf.png

この Codelab では、マテリアル テーマ設定によってできることの一部を説明します。この Codelab を通じて、アプリのデザインをマテリアル テーマ設定によって改善するためのアイデアが得られます。

カラーパレット

これから作成するライトモードとダークモードのカラーパレットを以下に示します。

この画像は、Woof アプリのライト カラーパターンです。

この画像は、Woof アプリのダーク カラーパターンです。

ライトモードとダークモードの完成したアプリを以下に示します。

ライトモード

ダークモード

タイポグラフィ

アプリで使用する書体スタイルは以下のとおりです。

8ea685b3871d5ffc.png

テーマファイル

Theme.kt ファイルは、アプリのテーマに関するすべての情報を保持するファイルです。色、タイポグラフィ、シェイプによって定義されます。これは重要なファイルです。Theme.kt ファイルには、アプリの色、タイポグラフィ、シェイプを設定するコンポーザブル WoofTheme() があります。

@Composable
fun WoofTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    // Dynamic color is available on Android 12+
    dynamicColor: Boolean = false,
    content: @Composable () -> Unit
) {
    val colorScheme = when {
        dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
            val context = LocalContext.current
            if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
        }

        darkTheme -> DarkColors
        else -> LightColors
    }
    val view = LocalView.current
    if (!view.isInEditMode) {
        SideEffect {
            setUpEdgeToEdge(view, darkTheme)
        }
    }

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

/**
 * Sets up edge-to-edge for the window of this [view]. The system icon colors are set to either
 * light or dark depending on whether the [darkTheme] is enabled or not.
 */
private fun setUpEdgeToEdge(view: View, darkTheme: Boolean) {
    val window = (view.context as Activity).window
    WindowCompat.setDecorFitsSystemWindows(window, false)
    window.statusBarColor = Color.Transparent.toArgb()
    val navigationBarColor = when {
        Build.VERSION.SDK_INT >= 29 -> Color.Transparent.toArgb()
        Build.VERSION.SDK_INT >= 26 -> Color(0xFF, 0xFF, 0xFF, 0x63).toArgb()
        // Min sdk version for this app is 24, this block is for SDK versions 24 and 25
        else -> Color(0x00, 0x00, 0x00, 0x50).toArgb()
    }
    window.navigationBarColor = navigationBarColor
    val controller = WindowCompat.getInsetsController(window, view)
    controller.isAppearanceLightStatusBars = !darkTheme
    controller.isAppearanceLightNavigationBars = !darkTheme
}

MainActivity.kt では、WoofTheme() を追加することでアプリ全体のマテリアル テーマ設定が定義されます。

class MainActivity : ComponentActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContent {
           WoofTheme {
               Surface(
                   modifier = Modifier.fillMaxSize()
               ) {
                   WoofApp()
               }
           }
       }
   }
}

WoofPreview() をご覧ください。WoofTheme() を追加することで、WoofPreview() でマテリアル テーマ設定が定義されます。

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

3. スターター コードを取得する

まず、スターター コードをダウンロードします。

または、GitHub リポジトリのクローンを作成してコードを入手することもできます。

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

コードは Woof app GitHub リポジトリで確認できます。

スターター コードを確認する

  1. Android Studio でスターター コードを開きます。
  2. [com.example.woof] > [data] > [Dog.kt] を開きます。これには、犬の写真、名前、年齢、特技を示す Dog data class が含まれます。また、犬のリストや、アプリのデータとして使用する情報も含まれています。
  3. [res] > [drawable] を開きます。これには、アプリアイコン、犬の画像、アイコンなど、このプロジェクトに必要なすべての画像アセットが含まれています。
  4. [res] > [values] > [strings.xml] を開きます。このファイルには、アプリで使用する文字列(アプリ名、犬の名前、説明など)が含まれています。
  5. MainActivity.kt を開きます。このファイルには、犬の写真、名前、年齢を表示する簡単なリストを作成するコードが含まれています。
  6. WoofApp() には、DogItem を表示する LazyColumn が含まれています。
  7. DogItem() には、犬の写真とその犬に関する情報を表示する Row が含まれています。
  8. DogIcon() は犬の写真を表示します。
  9. DogInformation() は犬の名前と年齢を表示します。
  10. WoofPreview() を使用すると、[Design] ペインでアプリのプレビューを表示できます。

エミュレータ / デバイスがライトモードになっていることを確認する

この Codelab ではライトモードとダークモードの両方を使用しますが、ほとんどの場合はライトモードです。始める前に、デバイスまたはエミュレータがライトモードになっていることを確認してください。

アプリをライトモードで表示するには、エミュレータまたは実機で次のように操作します。

  1. デバイスの設定アプリを開きます。
  2. ダークモードを検索してクリックします。
  3. ダークモードがオンになっている場合は、オフにします。

スターター コードを実行すると、最初の画面が表示されます。犬の写真、名前、年齢を示すリストです。このままでも機能しますが、見た目が良くないので修正します。

6d253ae50c63014d.png

4. 色を追加する

最初に Woof アプリのカラーパターンを変更します。

カラーパターンは、アプリで使用する色の組み合わせを示しています。色の組み合わせによってムードが変わり、アプリを使用するユーザーの感じ方に影響します。

Android システムでは、色は 16 進数の色値で表されます。16 進数色コードは番号記号(#)で始まり、その後に色の赤、緑、青(RGB)成分を表す 6 つの文字または数字が続きます。最初の 2 文字と数字は赤、次の 2 文字は緑、最後の 2 文字は青を表します。

これは色の作成に使用される 16 進数を示します。

色には、色の透明度を表す英字や数字のアルファ値を含めることもできます(#00 は不透明度 0%(完全に透明)、#FF は不透明度 100%(完全に不透明))。指定した場合、アルファ値は 16 進数色コードで番号記号(#)に続く最初の 2 文字です。アルファ値を指定しない場合は、#FF(不透明度 100%)とみなされます。

色と 16 進数値の例を以下に示します。

2753d8cdd396c449.png

マテリアル テーマビルダーを使用してカラーパターンを作成する

アプリのカスタム カラーパターンを作成するには、マテリアル テーマビルダーを使用します。

  1. このリンクをクリックしてマテリアル テーマビルダーに移動します。
  2. 左側のペインで [Core Colors] が表示されたら、[Primary] をクリックします。

マテリアル テーマビルダーの 4 つのコアカラーを示しています

  1. HCT のカラー選択ツールが開きます。

マテリアル テーマビルダーでカスタムカラーを選択する HCT カラー選択ツールです。

  1. アプリのスクリーンショットに表示されるカラーパターンを作成するには、このカラー選択ツールでプライマリ カラーを変更します。テキスト ボックスで、現在のテキストを #006C4C に置き換えます。これにより、アプリのプライマリ カラーが緑色になります。

緑色に設定された HCT のカラー選択ツールを示しています。

これによって、画面上のアプリが緑色のカラーパターンを採用するように更新されます。

HCT カラー選択ツールの色の変化に反応するマテリアル テーマビルダーのアプリを示しています。

  1. ページを下にスクロールすると、入力した色から生成されたライトモードとダークモードのフル カラーパターンが表示されます。

マテリアル テーマビルダーのライトスキーム

マテリアル テーマビルダーによって生成されたダークスキーム

主要な役割とその活用方法は次のとおりです。

  • プライマリ カラーは、UI の主要なコンポーネントに使用されます。
  • セカンダリ カラーは、UI の目立たないコンポーネントに使用されます。
  • ターシャリ カラーは、プライマリ カラーとセカンダリ カラーのバランスを保つため、または入力フィールドなどの要素に注意を引くための、対照的なアクセントに使用されます。
  • オンカラー要素は、パレット内の他の色のに配置され、主にテキスト、アイコン、ストロークに適用されます。カラーパレットでは、サーフェス色の上に表示される onSurface カラーと、プライマリ カラーの上部に表示される onPrimary カラーがあります。

これらのスロットによって一貫性のあるデザイン システムが実現し、関連するコンポーネントにも同様に色付けされるようになります。

色に関する理論的な話は以上です。次にこの美しいカラーパレットをアプリに追加してみましょう。

テーマにカラーパレットを追加する

マテリアル テーマビルダー ページでは、[Export] ボタンをクリックして、テーマビルダーで作成したカスタムテーマを含む Color.kt ファイルと Theme.kt ファイルをダウンロードできます。

これにより、作成したカスタムテーマをアプリに追加できるようになります。ただし、生成された Theme.kt ファイルにはダイナミック カラーのコードが含まれていないため(Codelab の後半で詳しく説明します)、ファイルをコピーします。

  1. Color.kt ファイルを開き、内容を以下のコードに置き換えて、新しいカラーパターンにコピーします。
package com.example.woof.ui.theme

import androidx.compose.ui.graphics.Color

val md_theme_light_primary = Color(0xFF006C4C)
val md_theme_light_onPrimary = Color(0xFFFFFFFF)
val md_theme_light_primaryContainer = Color(0xFF89F8C7)
val md_theme_light_onPrimaryContainer = Color(0xFF002114)
val md_theme_light_secondary = Color(0xFF4D6357)
val md_theme_light_onSecondary = Color(0xFFFFFFFF)
val md_theme_light_secondaryContainer = Color(0xFFCFE9D9)
val md_theme_light_onSecondaryContainer = Color(0xFF092016)
val md_theme_light_tertiary = Color(0xFF3D6373)
val md_theme_light_onTertiary = Color(0xFFFFFFFF)
val md_theme_light_tertiaryContainer = Color(0xFFC1E8FB)
val md_theme_light_onTertiaryContainer = Color(0xFF001F29)
val md_theme_light_error = Color(0xFFBA1A1A)
val md_theme_light_errorContainer = Color(0xFFFFDAD6)
val md_theme_light_onError = Color(0xFFFFFFFF)
val md_theme_light_onErrorContainer = Color(0xFF410002)
val md_theme_light_background = Color(0xFFFBFDF9)
val md_theme_light_onBackground = Color(0xFF191C1A)
val md_theme_light_surface = Color(0xFFFBFDF9)
val md_theme_light_onSurface = Color(0xFF191C1A)
val md_theme_light_surfaceVariant = Color(0xFFDBE5DD)
val md_theme_light_onSurfaceVariant = Color(0xFF404943)
val md_theme_light_outline = Color(0xFF707973)
val md_theme_light_inverseOnSurface = Color(0xFFEFF1ED)
val md_theme_light_inverseSurface = Color(0xFF2E312F)
val md_theme_light_inversePrimary = Color(0xFF6CDBAC)
val md_theme_light_shadow = Color(0xFF000000)
val md_theme_light_surfaceTint = Color(0xFF006C4C)
val md_theme_light_outlineVariant = Color(0xFFBFC9C2)
val md_theme_light_scrim = Color(0xFF000000)

val md_theme_dark_primary = Color(0xFF6CDBAC)
val md_theme_dark_onPrimary = Color(0xFF003826)
val md_theme_dark_primaryContainer = Color(0xFF005138)
val md_theme_dark_onPrimaryContainer = Color(0xFF89F8C7)
val md_theme_dark_secondary = Color(0xFFB3CCBE)
val md_theme_dark_onSecondary = Color(0xFF1F352A)
val md_theme_dark_secondaryContainer = Color(0xFF354B40)
val md_theme_dark_onSecondaryContainer = Color(0xFFCFE9D9)
val md_theme_dark_tertiary = Color(0xFFA5CCDF)
val md_theme_dark_onTertiary = Color(0xFF073543)
val md_theme_dark_tertiaryContainer = Color(0xFF244C5B)
val md_theme_dark_onTertiaryContainer = Color(0xFFC1E8FB)
val md_theme_dark_error = Color(0xFFFFB4AB)
val md_theme_dark_errorContainer = Color(0xFF93000A)
val md_theme_dark_onError = Color(0xFF690005)
val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6)
val md_theme_dark_background = Color(0xFF191C1A)
val md_theme_dark_onBackground = Color(0xFFE1E3DF)
val md_theme_dark_surface = Color(0xFF191C1A)
val md_theme_dark_onSurface = Color(0xFFE1E3DF)
val md_theme_dark_surfaceVariant = Color(0xFF404943)
val md_theme_dark_onSurfaceVariant = Color(0xFFBFC9C2)
val md_theme_dark_outline = Color(0xFF8A938C)
val md_theme_dark_inverseOnSurface = Color(0xFF191C1A)
val md_theme_dark_inverseSurface = Color(0xFFE1E3DF)
val md_theme_dark_inversePrimary = Color(0xFF006C4C)
val md_theme_dark_shadow = Color(0xFF000000)
val md_theme_dark_surfaceTint = Color(0xFF6CDBAC)
val md_theme_dark_outlineVariant = Color(0xFF404943)
val md_theme_dark_scrim = Color(0xFF000000)
  1. Theme.kt ファイルを開き、内容を以下のコードに置き換えて、テーマに新しい色を追加します。
package com.example.woof.ui.theme

import android.app.Activity
import android.os.Build
import android.view.View
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowCompat

private val LightColors = lightColorScheme(
    primary = md_theme_light_primary,
    onPrimary = md_theme_light_onPrimary,
    primaryContainer = md_theme_light_primaryContainer,
    onPrimaryContainer = md_theme_light_onPrimaryContainer,
    secondary = md_theme_light_secondary,
    onSecondary = md_theme_light_onSecondary,
    secondaryContainer = md_theme_light_secondaryContainer,
    onSecondaryContainer = md_theme_light_onSecondaryContainer,
    tertiary = md_theme_light_tertiary,
    onTertiary = md_theme_light_onTertiary,
    tertiaryContainer = md_theme_light_tertiaryContainer,
    onTertiaryContainer = md_theme_light_onTertiaryContainer,
    error = md_theme_light_error,
    errorContainer = md_theme_light_errorContainer,
    onError = md_theme_light_onError,
    onErrorContainer = md_theme_light_onErrorContainer,
    background = md_theme_light_background,
    onBackground = md_theme_light_onBackground,
    surface = md_theme_light_surface,
    onSurface = md_theme_light_onSurface,
    surfaceVariant = md_theme_light_surfaceVariant,
    onSurfaceVariant = md_theme_light_onSurfaceVariant,
    outline = md_theme_light_outline,
    inverseOnSurface = md_theme_light_inverseOnSurface,
    inverseSurface = md_theme_light_inverseSurface,
    inversePrimary = md_theme_light_inversePrimary,
    surfaceTint = md_theme_light_surfaceTint,
    outlineVariant = md_theme_light_outlineVariant,
    scrim = md_theme_light_scrim,
)

private val DarkColors = darkColorScheme(
    primary = md_theme_dark_primary,
    onPrimary = md_theme_dark_onPrimary,
    primaryContainer = md_theme_dark_primaryContainer,
    onPrimaryContainer = md_theme_dark_onPrimaryContainer,
    secondary = md_theme_dark_secondary,
    onSecondary = md_theme_dark_onSecondary,
    secondaryContainer = md_theme_dark_secondaryContainer,
    onSecondaryContainer = md_theme_dark_onSecondaryContainer,
    tertiary = md_theme_dark_tertiary,
    onTertiary = md_theme_dark_onTertiary,
    tertiaryContainer = md_theme_dark_tertiaryContainer,
    onTertiaryContainer = md_theme_dark_onTertiaryContainer,
    error = md_theme_dark_error,
    errorContainer = md_theme_dark_errorContainer,
    onError = md_theme_dark_onError,
    onErrorContainer = md_theme_dark_onErrorContainer,
    background = md_theme_dark_background,
    onBackground = md_theme_dark_onBackground,
    surface = md_theme_dark_surface,
    onSurface = md_theme_dark_onSurface,
    surfaceVariant = md_theme_dark_surfaceVariant,
    onSurfaceVariant = md_theme_dark_onSurfaceVariant,
    outline = md_theme_dark_outline,
    inverseOnSurface = md_theme_dark_inverseOnSurface,
    inverseSurface = md_theme_dark_inverseSurface,
    inversePrimary = md_theme_dark_inversePrimary,
    surfaceTint = md_theme_dark_surfaceTint,
    outlineVariant = md_theme_dark_outlineVariant,
    scrim = md_theme_dark_scrim,
)

@Composable
fun WoofTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    // Dynamic color is available on Android 12+
    dynamicColor: Boolean = false,
    content: @Composable () -> Unit
) {
    val colorScheme = when {
        dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
            val context = LocalContext.current
            if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
        }

        darkTheme -> DarkColors
        else -> LightColors
    }
    val view = LocalView.current
    if (!view.isInEditMode) {
        SideEffect {
            setUpEdgeToEdge(view, darkTheme)
        }
    }

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

/**
 * Sets up edge-to-edge for the window of this [view]. The system icon colors are set to either
 * light or dark depending on whether the [darkTheme] is enabled or not.
 */
private fun setUpEdgeToEdge(view: View, darkTheme: Boolean) {
    val window = (view.context as Activity).window
    WindowCompat.setDecorFitsSystemWindows(window, false)
    window.statusBarColor = Color.Transparent.toArgb()
    val navigationBarColor = when {
        Build.VERSION.SDK_INT >= 29 -> Color.Transparent.toArgb()
        Build.VERSION.SDK_INT >= 26 -> Color(0xFF, 0xFF, 0xFF, 0x63).toArgb()
        // Min sdk version for this app is 24, this block is for SDK versions 24 and 25
        else -> Color(0x00, 0x00, 0x00, 0x50).toArgb()
    }
    window.navigationBarColor = navigationBarColor
    val controller = WindowCompat.getInsetsController(window, view)
    controller.isAppearanceLightStatusBars = !darkTheme
    controller.isAppearanceLightNavigationBars = !darkTheme
}

WoofTheme() では、colorScheme valwhen ステートメントを使用します。

  • dynamicColor が true でビルド バージョンが S 以降の場合、デバイスが darkTheme かどうかを確認します。
  • ダークモードの場合、colorSchemedynamicDarkColorScheme に設定されます。
  • ダークモードでない場合は、dynamicLightColorScheme に設定されます。
  • アプリが dynamicColorScheme を使用していない場合、アプリが darkTheme かどうかを確認します。ダークモードの場合、colorSchemeDarkColors に設定されます。
  • いずれでもない場合、colorSchemeLightColors に設定されます。

Theme.kt ファイルでコピーしたファイルでは、dynamicColor が false に設定されており、作業中のデバイスはライトモードになっているため、colorSchemeLightColors に設定されます。

val colorScheme = when {
       dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
           val context = LocalContext.current
           if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
       }

       darkTheme -> DarkColors
       else -> LightColors
   }
  1. アプリを再実行すると、アプリバーの色が自動的に変更されていることがわかります。

b48b3fa2ecec9b86.png

カラー マッピング

マテリアル コンポーネントはカラースロットに自動的にマッピングされます。フローティング アクション ボタンなど、UI の他の主要なコンポーネントも、デフォルトでプライマリ カラーになっています。つまり、コンポーネントに明示的に色を割り当てる必要はありません。アプリでカラーテーマを設定すると、自動的にカラースロットにマッピングされます。これをオーバーライドするには、コード内で色を明示的に設定します。色の役割について詳しくは、こちらをご覧ください。

このセクションでは、DogIcon()DogInformation() を含む RowCard でラップし、リストアイテムの色を背景と区別します。

  1. コンポーズ可能な関数 DogItem() で、Row()Card() でラップします。
Card() {
   Row(
       modifier = modifier
           .fillMaxWidth()
           .padding(dimensionResource(id = R.dimen.padding_small))
   ) {
       DogIcon(dog.imageResourceId)
       DogInformation(dog.name, dog.age)
   }
}
  1. CardDogItem() の最初の子コンポーザブルになっているため、DogItem() から Card に修飾子を渡し、Row の修飾子を Modifier の新しいインスタンスに更新します。
Card(modifier = modifier) {
   Row(
       modifier = Modifier
           .fillMaxWidth()
           .padding(dimensionResource(id = R.dimen.padding_small))
   ) {
       DogIcon(dog.imageResourceId)
       DogInformation(dog.name, dog.age)
   }
}
  1. WoofPreview() をご覧ください。Card コンポーザブルにより、リストアイテムの色が自動的に変更されました。色はきれいに見えますが、リストアイテムの間にはスペースがありません。

6d49372a1ef49bc7.png

ディメンション ファイル

strings.xml を使用してアプリに文字列を保存する場合と同じように、dimens.xml というファイルを使用してディメンションの値を格納することもおすすめします。これは、値をハードコードする手間を省き、必要に応じて 1 か所で値を変更できるため便利です。

[app] > [res] > [values] > [dimens.xml] に移動して、ファイルを確認します。padding_smallpadding_mediumimage_size のディメンション値が格納されます。これらのディメンションはアプリ全体で使用されます。

<resources>
   <dimen name="padding_small">8dp</dimen>
   <dimen name="padding_medium">16dp</dimen>
   <dimen name="image_size">64dp</dimen>
</resources>

dimens.xml ファイルから値を追加する正しい形式は次のとおりです。

ディメンション リソースから値を適切に追加する方法を説明します。

たとえば、padding_small を追加するには、dimensionResource(id = R.dimen.padding_small) を渡します。

  1. WoofApp() で、DogItem() の呼び出しに padding_small を含む modifier を追加します。
@Composable
fun WoofApp() {
    Scaffold { it ->
        LazyColumn(contentPadding = it) {
            items(dogs) {
                DogItem(
                    dog = it,
                    modifier = Modifier.padding(dimensionResource(R.dimen.padding_small))
                )
            }
        }
    }
}

WoofPreview() で、リストアイテム間がより明確になりました。

c54f870f121fe02.png

ダークモード

Android システムには、デバイスをダークモードに切り替えるオプションがあります。ダークモードでは、より暗く、落ち着いた色が使用されており、以下の効果があります。

  • 電力使用量を大幅に削減できます(削減できる量はデバイスの画面テクノロジーに左右されます)。
  • 視力の低いユーザーや明るい光に敏感なユーザーにとって、画面の見やすさが向上します。
  • すべてのユーザーにとって、暗い場所でのデバイスの使いやすさが向上します。

アプリでフォースダークにオプトインすると、システムによってダークモードが実装されます。ただし、ダークモードの実装はユーザー エクスペリエンス向上に有効であるため、アプリのテーマについてはデベロッパーが完全に制御できます。

デベロッパーが独自にダークモードを選択する際は、ダークモードの色がユーザー補助のコントラスト標準に適合していることをご確認ください。ダークモードでは暗いサーフェス色を使用し、色のアクセントは限定されます。

ダークモードをプレビュー表示する

ダークモードの色は、前のステップですでに追加されています。ダークモードの動作を確認するには、別のプレビュー コンポーザブルを MainActivity.kt に追加します。それにより、コードの UI レイアウトを変更したときに、ライトモードとダークモードのプレビューがどのように表示されるかを同時に確認できます。

  1. WoofPreview() で、WoofDarkThemePreview() という新しい関数を作成し、@Preview@Composable というアノテーションを付けます。
@Preview
@Composable
fun WoofDarkThemePreview() {

}
  1. DarkThemePreview() 内で WoofTheme() を追加します。WoofTheme() を追加しないと、アプリに追加したスタイルは表示されません。darkTheme パラメータを true に設定します。
@Preview
@Composable
fun WoofDarkThemePreview() {
   WoofTheme(darkTheme = true) {

   }
}
  1. WoofTheme() 内で WoofApp() を呼び出します。
@Preview
@Composable
fun WoofDarkThemePreview() {
   WoofTheme(darkTheme = true) {
       WoofApp()
   }
}

[Design] ペインで下にスクロールして、アプリをダークモードで表示します。アプリ / リストアイテムの背景がさらに暗くなり、テキストが明るくなります。ダークモードとライトモードの違いを比較します。

ダークモード

ライトモード

デバイスまたはエミュレータでダークモードを表示する

エミュレータまたは実機でアプリをダークモードで表示するには:

  1. デバイスの設定アプリを開きます。
  2. ダークモードを検索してクリックします。
  3. ダークモードをオンにします。
  4. Woof アプリを再度開くと、ダークモードで表示されます。

bc31a94207265b08.png

この Codelab ではライトモードに重点を置いているため、ダークモードをオフにしてからアプリの操作を進めてください。

  1. デバイスの設定アプリを開きます。
  2. [Display] を選択します。
  3. [Dark theme] をオフにします。

セクションの最初と現在とで、アプリの外観がどのように変わったかを比較してください。リストアイテムやテキストがより明瞭になり、カラーパターンの視覚的な魅力が増しているはずです。

色を使わない

色を使う(ライトモード)

色を使う(ダークモード)

ダイナミック カラー

マテリアル 3 ではユーザーのパーソナライズに重点を置いています。マテリアル 3 の新機能であるダイナミック カラーでは、ユーザーの壁紙に基づいてアプリのテーマを作成します。そのため、ユーザーが緑色が好きで、スマートフォンの背景が青の場合、それを反映している Woof アプリも青色になります。動的なテーマ設定は、Android 12 以降を搭載した特定のデバイスでのみ行われます。

カスタムテーマは、強いブランディング カラーを持つアプリに使用できます。また、動的なテーマ設定に対応していないデバイスにも実装し、アプリにテーマ設定します。

  1. ダイナミック カラーを有効にするには、Theme.kt を開き、WoofTheme() コンポーザブルに移動して dynamicColor パラメータを true に設定します。
@Composable
fun WoofTheme(
   darkTheme: Boolean = isSystemInDarkTheme(),
   dynamicColor: Boolean = true,
   content: @Composable () -> Unit
)
  1. デバイスまたはエミュレータの背景を変更するには、[設定] に移動し、[壁紙] を検索します。
  2. 壁紙を特定の色または色のセットに変更します。
  3. アプリを再実行すると動的なテーマが表示されます(なお、ダイナミック カラーを表示するには、デバイスやエミュレータが Android 12 以降である必要があります)。さまざまな壁紙を使用して、自由にお試しください。

710bd13f6b189dc5.png

  1. この Codelab ではカスタムテーマ設定に重点を置いているため、次に進む前に dynamicColor を無効にしてください。
@Composable
fun WoofTheme(
   darkTheme: Boolean = isSystemInDarkTheme(),
   dynamicColor: Boolean = false,
   content: @Composable () -> Unit
)

5. シェイプを追加する

シェイプを適用すると、コンポーザブルのデザインが大幅に変わる場合があります。シェイプはユーザーの注意を引き、コンポーネントを明確に示し、状態を伝え、ブランドを表現するために役立ちます。

多くのシェイプは、角が丸い長方形を表す RoundedCornerShape を使用して定義されています。渡される数値によって角の丸みが決まります。RoundedCornerShape(0.dp) を使用すると、長方形の角は丸くなりません。RoundedCornerShape(50.dp) を使用すると、角が完全な円形になります。

0.dp

25.dp

50.dp

シェーピングありの Woof リストアイテム

シェーピングありの Woof リストアイテム

シェーピングありの Woof リストアイテム

各隅に異なる丸め率を設定して、シェイプをさらにカスタマイズすることもできます。さまざまなシェイプを試してみましょう。

左上: 50.dp
左下: 25.dp
右上: 0.dp
右下: 15.dp

左上: 15.dp
左下: 50.dp
右上: 50.dp
右下: 15.dp

左上: 0.dp
左下: 50.dp
右上: 0.dp
右下: 50.dp

シェーピングありの Woof リストアイテム

シェーピングありの Woof リストアイテム

シェーピングありの Woof リストアイテム

Compose のコンポーネントのシェイプを定義するには、Shape.kt ファイルを使用します。コンポーネントには、大、中、小の 3 種類があります。このセクションでは、Card コンポーネント(medium サイズとして定義)を変更します。コンポーネントはサイズに基づいてシェイプ カテゴリにグループ化されます。

このセクションでは、犬の画像を丸くシェーピングし、リストアイテムのシェイプを変更します。

犬の画像を円形にする

  1. Shape.kt ファイルを開き、small パラメータが RoundedCornerShape(50.dp) に設定されていることを確認します。これは画像を円形にシェーピングするために使用されます。
val Shapes = Shapes(
   small = RoundedCornerShape(50.dp),
)
  1. MainActivity.kt を開きます。DogIcon() で、clip 属性を Imagemodifier に追加します。画像がシェイプにクリップされます。MaterialTheme.shapes.small を渡します。
import androidx.compose.ui.draw.clip

@Composable
fun DogIcon(
   @DrawableRes dogIcon: Int,
   modifier: Modifier = Modifier
) {
   Image(
       modifier = modifier
           .size(dimensionResource(id = R.dimen.image_size))
           .padding(dimensionResource(id = R.dimen.padding_small))
           .clip(MaterialTheme.shapes.small),

WoofPreview() を見ると、犬のアイコンが円形になっていることがわかります。しかし、一部の写真の両側が切り取られ、完全な円形として表示されていません。

1d4d1e5eaaddf71e.png

  1. すべての写真を円形にするには、ContentScale 属性と Crop 属性を追加します。画像が収まるように切り抜かれます。contentScaleImage の属性であり、modifier の一部ではありません。
import androidx.compose.ui.layout.ContentScale

@Composable
fun DogIcon(
   @DrawableRes dogIcon: Int,
   modifier: Modifier = Modifier
) {
   Image(
       modifier = modifier
           .size(dimensionResource(id = R.dimen.image_size))
           .padding(dimensionResource(id = R.dimen.padding_small))
           .clip(MaterialTheme.shapes.small),
       contentScale = ContentScale.Crop,

これは、完全な DogIcon() コンポーザブルです。

@Composable
fun DogIcon(
    @DrawableRes dogIcon: Int,
    modifier: Modifier = Modifier
) {
    Image(
        modifier = modifier
            .size(dimensionResource(R.dimen.image_size))
            .padding(dimensionResource(R.dimen.padding_small))
            .clip(MaterialTheme.shapes.small),
        contentScale = ContentScale.Crop,
        painter = painterResource(dogIcon),

        // Content Description is not needed here - image is decorative, and setting a null content
        // description allows accessibility services to skip this element during navigation.

        contentDescription = null
    )
}

WoofPreview() では、アイコンが円形に表示されます。

fc93106990f5e161.png

リストアイテムにシェイプを追加する

このセクションでは、リストアイテムにシェイプを追加します。リストアイテムはすでに Card を介して表示されています。Card は、サーフェスとして 1 つのコンポーザブルを含めることができ、また装飾オプションも用意されています。装飾は枠線やシェイプなどを使用して追加できます。このセクションでは、Card を使用してリストアイテムにシェイプを追加します。

シェイプのディメンションが追加された Woof リストアイテム

  1. Shape.kt ファイルを開きます。Card はミディアム コンポーネントであるため、Shapes オブジェクトの medium パラメータを追加します。このアプリでは、リストアイテムの右上隅と左下隅ですが、完全な円形にはしません。それには、16.dpmedium 属性に渡します。
medium = RoundedCornerShape(bottomStart = 16.dp, topEnd = 16.dp)

Card はデフォルトでミディアム シェイプを使用しているため、明示的にミディアム シェイプに設定する必要はありません。プレビューで、新しくシェーピングされた Card をご確認ください。

シェーピングされたカードが表示された Woof のプレビュー

WoofTheme()Theme.kt ファイルに戻って MaterialTheme() を見ると、shapes 属性が、更新した Shapes val に設定されていることがわかります。

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

以下に、シェーピング前後のリストアイテムの比較を示します。シェーピングを加えることで、アプリの魅力がどれだけ高まるかに注目してください。

シェーピングなし

シェーピングあり

6. タイポグラフィを追加する

マテリアル デザインのタイプスケール

タイプスケールは、アプリ全体で使用できるフォント スタイルのセレクションです。柔軟でありながら一貫性のあるスタイルを保証します。マテリアル デザインのタイプスケールには、タイプシステムでサポートされる 15 のフォント スタイルが含まれています。名前とグループ化は、表示、見出し、タイトル、本文、ラベルに簡略化され、それぞれに大、中、小のサイズがあります。この選択が必要になるのは、アプリをカスタマイズする場合のみです。タイプスケールのカテゴリ別の設定がわからない場合は、デフォルトのタイポグラフィ スケールを使用できます。

999a161dcd9b0ec4.png

タイプスケールには、それぞれ意図された用途と意味を持つ、再利用可能なテキスト カテゴリが含まれています。

ディスプレイ

最大のテキストであるディスプレイ スタイルは、短く重要なテキストや数字用に予約されています。大画面では特に高い効果を発揮します。

見出し

見出しは、小さい画面上の短く強調されたテキストに適しています。これらのスタイルは、テキストの主要な文や重要なコンテンツ領域をマークする場合に便利です。

タイトル

タイトルは見出しスタイルよりも小さく、比較的短い中強調のテキストに使用されます。

本文

本文のスタイルは、アプリ内のテキストの長い文に使用されます。

ラベル

ラベルのスタイルは小さく、実用的なスタイルであり、コンポーネント内のテキストや、キャプションなどのコンテンツ本文の非常に小さいテキストに使用されます。

フォント

Android プラットフォームにはさまざまなフォントが用意されていますが、デフォルトで用意されていないフォントを使用してアプリをカスタマイズすることもできます。カスタム フォントを使用すれば、個性を表現できます。ブランディングにも適しています。

このセクションでは、Abril FatfaceMontserrat BoldMontserrat Regular というカスタム フォントを追加します。displayLarge 見出しと displayMedium 見出し、マテリアル タイプ システムの bodyLarge テキストを使用し、これらをアプリのテキストに追加します。

フォントの Android リソース ディレクトリを作成します。

アプリにフォントを追加する前に、フォントのディレクトリを作成する必要があります。

  1. Android Studio のプロジェクト ビューで、res フォルダを右クリックします。
  2. [New] > [Android Resource Directory] を選択します。

この画像は、Android のリソース ディレクトリまでファイル構造内を移動する様子を示しています。

  1. ディレクトリの名前を「font」にして、[Resource type] を「font」に設定し、[OK] をクリックします。

この画像は、新しいリソース ディレクトリを使用したフォント ディレクトリの追加を示しています。

  1. [res] > [font] にある新しいフォント リソース ディレクトリを開きます。

カスタム フォントをダウンロードする

Android プラットフォームでは提供されていないフォントを使用するため、カスタム フォントをダウンロードする必要があります。

  1. https://fonts.google.com/ にアクセスします。
  2. Montserrat」を検索して、[Download family] をクリックします。
  3. zip ファイルを解凍します。
  4. ダウンロードした Montserrat フォルダを開きます。static フォルダに Montserrat-Bold.ttfMontserrat-Regular.ttf があります(ttf は、フォントのファイル形式である TrueType フォントの略です)。両方のフォントを選択し、Android Studio のプロジェクトのフォント リソース ディレクトリにドラッグします。

この画像は、Montserrat フォントの静的フォルダの内容を示しています。

  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_Regular.ttfabril_fatface_regular.ttf に変更します。

3 つのカスタム フォント ファイルを追加したプロジェクトのフォント リソース ディレクトリは、次のようになります。

この画像は、フォント フォルダに追加されたフォント ファイルを示しています。

フォントを初期化する

  1. プロジェクト ウィンドウで、[ui.theme] > [Type.kt] を開きます。インポート ステートメントの下、Typography val の上で、ダウンロードしたフォントを初期化します。まず、Abril FatfaceFontFamily に設定して初期化し、フォント ファイル abril_fatface_regular を指定して Font を渡します。
​​import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import com.example.woof.R

val AbrilFatface = FontFamily(
   Font(R.font.abril_fatface_regular)
)
  1. Abril Fatface の下にある MontserratFontFamily に設定して初期化し、フォント ファイル montserrat_regular を指定して Font に渡します。montserrat_bold については FontWeight.Bold も指定します。太字のフォント ファイルを渡しても、Compose はファイルが太字であることを認識しないため、ファイルを FontWeight.Bold に明示的にリンクする必要があります。
import androidx.compose.ui.text.font.FontWeight

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 種類の書体のパラメータがあります。これは必要な数だけ定義できます。このアプリでは、displayLargedisplayMediumbodyLarge を設定します。このアプリの次の部分では labelSmall を使用するため、ここで追加します。

追加する見出しのフォント、太さ、サイズを以下の表に示します。

8ea685b3871d5ffc.png

  1. displayLarge 属性には TextStyle を設定し、fontFamilyfontWeightfontSize に上記の表の情報を入力します。それにより、displayLarge に設定されたテキストのフォントはすべて通常の太さの Abril Fatface に設定され、fontSize36.sp になります。

displayMediumlabelSmallbodyLarge についてもこの手順を繰り返します。

import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.sp

val Typography = Typography(
   displayLarge = TextStyle(
       fontFamily = AbrilFatface,
       fontWeight = FontWeight.Normal,
       fontSize = 36.sp
   ),
   displayMedium = TextStyle(
       fontFamily = Montserrat,
       fontWeight = FontWeight.Bold,
       fontSize = 20.sp
   ),
   labelSmall = TextStyle(
       fontFamily = Montserrat,
       fontWeight = FontWeight.Bold,
       fontSize = 14.sp
   ),
   bodyLarge = 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. 短く重要な情報である dogName のスタイルとして displayMedium を追加します。小さい文字にも対応する bodyLargedogAge のスタイルとして追加します。
@Composable
fun DogInformation(
   @StringRes dogName: Int,
   dogAge: Int,
   modifier: Modifier = Modifier
) {
   Column(modifier = modifier) {
       Text(
           text = stringResource(dogName),
           style = MaterialTheme.typography.displayMedium,
           modifier = Modifier.padding(top = dimensionResource(id = R.dimen.padding_small))
       )
       Text(
           text = stringResource(R.string.years_old, dogAge),
           style = MaterialTheme.typography.bodyLarge
       )
   }
}
  1. これで、WoofPreview() で犬の名前は 20.sp で太字の Montserrat フォントになり、犬の年齢は 14.sp で通常の Montserrat フォントになります。

タイポグラフィが追加された Woof のプレビュー

以下に、タイポグラフィを追加した前後のリストアイテムを並べて示します。犬の名前と犬の年齢のフォントの違いに注目してください。

タイポグラフィを使用しない場合

タイポグラフィを使用した場合

7. トップバーを追加する

Scaffold は、さまざまなコンポーネントや画面要素(ImageRowColumn など)のためのスロットが用意されたレイアウトです。Scaffold には、このセクションで使用する TopAppBar のためのスロットも用意されています。

TopAppBar はさまざまな用途に使用できますが、ここではブランディングとアプリの個性を出すために使用します。TopAppBar には、中央、小、中、大の 4 種類があります。この Codelab では、中央の上部アプリバーを実装します。以下のスクリーンショットのようなコンポーザブルを作成し、ScaffoldtopBar セクションに配置します。

172417c7b64372f7.png

このアプリの場合、トップバーはロゴの画像とアプリのタイトルのテキストを含む Row で構成されています。このロゴは、グラデーションが施されたかわいらしい足跡とアプリのタイトルで構成されています。

736f411f5067e0b5.png

トップバーに画像とテキストを追加する

  1. MainActivity.kt で、WoofTopAppBar() というコンポーザブルを作成し、必要に応じて modifier を指定します。
@Composable
fun WoofTopAppBar(modifier: Modifier = Modifier) {

}
  1. Scaffold は、スキャフォールド コンテンツのインセットを指定するために役立つ contentWindowInsets パラメータをサポートしています。WindowInsets は、アプリがシステム UI と交差できる画面の部分であり、これらの要素は PaddingValues パラメータを介してコンテンツ スロットに渡されます。詳しくは、こちらをご覧ください。

contentWindowInsets 値は contentPadding として LazyColumn に渡されます。

@Composable
fun WoofApp() {
    Scaffold { it ->
        LazyColumn(contentPadding = it) {
            items(dogs) {
                DogItem(
                    dog = it,
                    modifier = Modifier.padding(dimensionResource(R.dimen.padding_small))
                )
            }
        }
    }
}
  1. Scaffold 内に topBar 属性を追加して、WoofTopAppBar() に設定します。
Scaffold(
   topBar = {
       WoofTopAppBar()
   }
)

WoofApp() コンポーザブルは次のようになります。

@Composable
fun WoofApp() {
    Scaffold(
        topBar = {
            WoofTopAppBar()
        }
    ) { it ->
        LazyColumn(contentPadding = it) {
            items(dogs) {
                DogItem(
                    dog = it,
                    modifier = Modifier.padding(dimensionResource(R.dimen.padding_small))
                )
            }
        }
    }
}

WoofTopAppBar() には何もないため、WoofPreview() に変更はありません。これを変更しましょう。

タイポグラフィが適用された Woof のプレビュー

  1. WoofTopAppBar() Composable 内に CenterAlignedTopAppBar() を追加し、修飾子パラメータを WoofTopAppBar() に渡された修飾子に設定します。
import androidx.compose.material3.CenterAlignedTopAppBar

@Composable
fun WoofTopAppBar(modifier: Modifier = Modifier) {
   CenterAlignedTopAppBar(
       modifier = modifier
   )
}
  1. title パラメータには、CenterAlignedTopAppBarImageText を保持する Row を渡します。
@Composable
fun WoofTopAppBar(modifier: Modifier = Modifier){
   CenterAlignedTopAppBar(
       title = {
           Row() {

           }
       },
       modifier = modifier
   )
}
  1. ロゴ ImageRow に追加します。
  • modifier の画像サイズを dimens.xml ファイルの image_size として設定し、パディングを dimens.xml ファイルの padding_small に設定します。
  • painter を使用して、Image をドローアブル フォルダの ic_woof_logo に設定します。
  • contentDescriptionnull に設定します。このアプリロゴによって、視覚に障がいのあるユーザー向けのセマンティック情報は提供されないため、コンテンツの説明を追加する必要はありません。
Row() {
   Image(
       modifier = Modifier
           .size(dimensionResource(id = R.dimen.image_size))
           .padding(dimensionResource(id = R.dimen.padding_small)),
       painter = painterResource(R.drawable.ic_woof_logo),
       contentDescription = null
   )
}
  1. 次に、Text コンポーザブルを Image. の後の Row 内に追加します。
  • stringResource() を使用して app_name の値に設定します。テキストにアプリの名前が設定されます。この名前は strings.xml に保存されています。
  • アプリ名は短く重要なテキストであるため、テキストのスタイルは displayLarge に設定します。
Text(
   text = stringResource(R.string.app_name),
   style = MaterialTheme.typography.displayLarge
)

トップ アプリバーのある Woof プレビュー

WoofPreview() では、このように配置されています。アイコンとテキストが縦方向に揃っていないため、見た目が少しずれています。

  1. これを修正するには、verticalAlignment 値パラメータを Row に追加し、Alignment.CenterVertically に設定します。
import androidx.compose.ui.Alignment

Row(
   verticalAlignment = Alignment.CenterVertically
)

トップ アプリバーが垂直方向に中央揃えされた Woof プレビュー

見た目もかなり良くなりました。

WoofTopAppBar() コンポーザブル全体は次のとおりです。

@Composable
fun WoofTopAppBar(modifier: Modifier = Modifier) {
   CenterAlignedTopAppBar(
       title = {
           Row(
               verticalAlignment = Alignment.CenterVertically
           ) {
               Image(
                   modifier = Modifier
                       .size(dimensionResource(id = R.dimen.image_size))
                       .padding(dimensionResource(id = R.dimen.padding_small)),
                   painter = painterResource(R.drawable.ic_woof_logo),

                   contentDescription = null
               )
               Text(
                   text = stringResource(R.string.app_name),
                   style = MaterialTheme.typography.displayLarge
               )
           }
       },
       modifier = modifier
   )
}

アプリを実行します。TopAppBar によって、アプリが統一感を持った美しいデザインになったことを確認してください。

トップ アプリバーなし

トップ アプリバーあり

では、ダークモードで完成したアプリを見てみましょう。

2776e6a45cf3434a.png

お疲れさまでした。これでこの Codelab は終了です。

8. 解答コードを取得する

この 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 Studio で開くこともできます。

解答コードを確認する場合は、GitHub で表示します

9. まとめ

今回は初めてのマテリアル アプリを作成しました。ライトモードとダークモード用のカスタム カラーパレットを作成し、さまざまなコンポーネントのシェイプを作成するとともに、フォントをダウンロードしてアプリに追加し、美しいトップバーを作成して全体に統一感を持たせました。この Codelab で習得したスキルを生かして、色、シェイプ、タイポグラフィを変更して、自分だけのアプリにカスタマイズしましょう。

概要

  • マテリアル テーマ設定では、色、タイポグラフィ、シェイプのカスタマイズに関するガイダンスにより、アプリにマテリアル デザインを適用できます。
  • Theme.kt ファイルでは、テーマが定義されています。このアプリの場合、[your app name]+Theme()-WoofTheme() という名前のコンポーザブルを介してテーマが定義されています。この関数内で、MaterialTheme オブジェクトはアプリの colortypographyshapescontent を設定します。
  • Color.kt では、アプリで使用する色が一覧表示されます。そして、Theme.kt で、特定のスロットに LightColorPaletteDarkColorPalette の色を割り当てます。すべてのスロットに割り当てる必要はありません。
  • アプリでフォースダークにオプトインすると、システムによってダークモードが実装されます。ただし、デベロッパーがダークモードを実装してアプリのテーマを完全に制御すると、ユーザー エクスペリエンス向上にさらに有効です。
  • Shape.kt では、アプリのシェイプを定義します。シェイプには 3 つのサイズ(大、中、小)があり、角の丸みを指定できます。
  • シェイプはユーザーの注意を引き、コンポーネントを明確に示し、状態を伝え、ブランドを表現するために役立ちます。
  • Type.kt では、フォントを初期化し、マテリアル デザインのタイプスケールに fontFamilyfontWeightfontSize を割り当てます。
  • マテリアル デザインのタイプスケールには、アプリとそのコンテンツのニーズに対応する、多様で広範なスタイルが用意されています。タイプスケールは、タイプシステムでサポートされる 15 のスタイルを組み合わせたものです。

10. 関連リンク