📝

Android Basic with ComposeのUnit3で学んだことをまとめてみる: Material Design

2024/11/13に公開

はじめに

こんにちは、某SIerでSEをやっているnekorush14です。
この記事は絶賛再*n入門しているAndroid開発について、Google公式のLearning Courseを通して学んだことをアウトプットするシリーズです。

Jetpack Composeに関するCourseのUnit3で得た知見を話します。
https://developer.android.com/courses/android-basics-compose/unit-3?hl=en

前回の記事はこちら👇
https://zenn.dev/nekorush14/articles/fb75cebb5f40a7

今回はUnit 3の後半部分であるMaterial Designについてまとめます。

Material Design

Material Designとは、Googleが提唱するUIデザインのベストプラクティをサポートするガイドライン・コンポーネント・ツールのAdaptiveなシステムのことです。

Android、Web、Flutter向けに実装が適用されており、ライブラリを使用することにより比較的小さいコストでMaterial Designのガイドラインに従ったアプリを構築できます。

Jetpack ComposeはMaterial Designとの親和性が高く、アプリケーションのテーマとしてMaterial Designを簡単に適用できます。Theme.ktでは、アプリケーションのデザインテーマに関する以下の情報を保持しており、一元管理できます。

  • Color
  • Typography
  • Shape

Theme.ktで定義するThemeもComposableであり、Jetpack Compose内のComposableから呼び出すことができます。

Composableでの文字色指定
Text(
    text = stringResource(R.strings.example),
    style = TextStyle(
        color = MaterialTheme.colorScheme.onPrimary, // Themeで指定したonPrimary色を使用する
    )
)

アプリケーションに対するテーマの指定はonCreate内のsetContentで行います。

アプリケーション全体にThemeを適用する
override fun onCreate(savedInstanceState: Bundle?) {
    // ...
    setContent {
        // プロジェクトをExampleという名前で作成した場合のTheme指定 (デフォルト状態)
        ExampleTheme {
            // ...
        }
    }
}

上記の例はAndroidのプロジェクトを生成した直後の状態です。
デフォルトで<プロジェクト名>ThemeというComposableがTheme.ktに定義されており、それを指定しています。

以降はColor、Typography、Shapeについてそれぞれまとめてみます。
また、同時に扱われたAnimationについてもまとめてみます。

Colors

  • Androidのカラースキームは16進かつ、alpha付きのRGBで表される

    • #FF808080: Alpha:0xFF, Red:0x80, Green:0x80, Blue:0x80
  • カラースキームを生成するためにMaterial Theme Builderを使用するとよい

  • PrimaryはUI全体の主要なコンポーネントで使用される

  • SecondaryはUI内部の目立たないコンポーネントで使用される

  • TertiaryはPrimaryとSecondaryのバランスを取ったり、Inputフィールドなどに注意を惹かせるためのアクセントとして使用される

  • onが付くカラーはonが付いていないカラーの上に表示する際の色を表す

    • テキスト、アイコン、ストロークで使用される
  • APIレベル31以降(Android 12以降)であればユーザが設定しているデバイスの壁紙に基づいた配色を適用できる

    • dynamicDarkColorSchemedynamicLightColorSchemeを使用する
  • Colors.ktに色を指定し、Theme.kt内でカラースキームを生成する

    • material3.darkColorSchemematerial3.lightColorSchemeを使用する
  • Themeを適用すると各カラーの役割に応じてThemeで設定した色が各コンポーネントへ自動的に割り当てられる

    • コンポーネント内で明示的に色を指定するとオーバーライドできる
  • 文字列をstring.xmlで管理するのと同様にディメンション値(dpの値)をdimens.xmlで管理するとよい

    • プロダクトコードにハードコードする必要がなく、一元管理できる
      • プロダクトコードでマジックナンバーのハードコードを避けられる
    • プロダクトコードで参照するにはdimensionResourceを使用する
      • リソース本体には文字列リソースと同じくRクラスを使用する

  • ダークテーマ

    • バッテリー使用量の削減や暗い環境でのユーザビリティなどからAndroidにはデバイスをダークテーマに切り替えるオプションがある
    • Force Darkをオプトイン可能だが、アプリケーションのテーマで実装より良いUXが得られる
    • 独自のダークテーマを作成する場合、ダークテーマの配色がアクセシビリティコントラストの標準を満たす必要がある
    • Previewでもダークモードの配色を確認可能

  • Dynamic Color

    • Material3はユーザーのパーソナライズに重点を置いている
    • Dynamic Colorはユーザーの壁紙に応じてアプリのテーマを作成する
    • ブランドカラーが強いアプリケーションやDynamic ColorをサポートしないAndroidに対してカスタムテーマを作成する
      • 前述のmaterial3.darkColorSchemematerial3.lightColorSchemeを使用する方法

Shape

  • RoundedCornerShapeを使用すると適用したコンポーネントの四隅を丸める事ができる
    • 引数にどのくらいラウンドさせるかをdpで指定する
    • 四隅を個別に指定できる
    • Material3のShapesを使用すると大きさ事にShapeを定義できる
    • Shapeを使用した際にコンテンツが見切れてしまう場合はcontentScaleにCrop属性を付与することでトリミングされ画像が収まるようになる
      • contentScaleはmodifierではなくImage Composableの属性
  • デフォルトのShapeではなくRoundedCornerShapeなどを使いカスタムすることでアプリケーションの見た目がはるかに魅力的となる

Typography

  • マテリアルデザインには役割に応じてフォントサイズが用意されている
    • タイトル、見出し、タイトル、本文など
  • Androidでは様々なフォントが適用されているが、デフォルトで提供されていないフォントを使用することもできる
    • resfontという名称でAndroid Resource Directoryを作成する
    • 作成したディレクトリにフォントを配置する
      • 名称はsnake_caseで記載する
      • FontFamilyを使用することでカスタムフォントファミリーを定義できる
        • Bold指定をする際はFont()の第2引数にFontWeight.Boldを指定する
    • Typographyを使用して役割ごとにTextStyleを定義できる
      • TextStylefontFamilyfontWeightfontSizeなどを定義できる

Animation

  • Jetpack Composeでは様々なアニメーションが用意されている
  • アニメーションの指定もModifierを使用する
    • コンテンツのサイズ(例えばリスト要素の高さなど)をアニメーションさせるときはanimateContentSizeを使用する
      • 実際のサイズはRuntimeで決めることが難しいため、animationSpecを指定してどのようにアニメーションさせるかを宣言する
    • 例えばspringアニメーションを使用すると、バネの伸縮をもしたアニメーションを適用できる
      • springアニメーションではdampingRatiostiffnessにより動きを定義できる
  • animate*AsStateは指定した値に向かって現在の値からアニメーションさせることができる
    • *にはFloat, Color, Dp, Size, Offset, Intなどの汎用的な型がある
    • animateValueAsStateはそれ以外のデータ型をサポートする
      // expandedはコンポーネントが展開されているかどうかを示すフラグ
      val color by animateColorAsState(
          targetValue = if (expanded) MaterialTheme.colorScheme.tertiaryContainer
              else MaterialTheme.colorScheme.primaryContainer
      )
      

まとめ

今回はUnit3で扱われたMaterial Designについてまとめました。
Androidでは簡単にMaterial Designを適用でき、最小のコストで洗練されたデザインを適用可能であると感じました。

次回はUnit4になります。
Unit4はいよいよArchitectureとNavigationの話となります。

参考資料

Discussion