スタイルの基礎

アプリ全体でスタイルを採用するには、次の 3 つの方法があります。

  1. Style パラメータを公開する既存のコンポーネントで直接使用する。
  2. Modifier.styleable を使用して、 コンポーザブルで Style パラメータを受け入れないレイアウトにスタイルを適用する。
  3. 独自のカスタム デザイン システムで Modifier.styleable{} を使用し、独自のコンポーネントでスタイル パラメータを公開する。

スタイルで使用可能なプロパティ

スタイルは、修飾子でサポートされているプロパティの多くをサポートしています。ただし、修飾子であるすべてのものをスタイルで複製できるわけではありません。インタラクション、カスタム描画、プロパティのスタッキングなど、特定の動作には修飾子が必要です。

グループ化 プロパティ 子に継承される
レイアウトとサイズ設定
パディング contentPadding(内側)と externalPadding(外側)。方向、水平、垂直、全辺のバリエーションで使用できます。 いいえ
サイズ fillWidth/Height/Size()widthheightsizeDpDpSizeFloat の分数に対応)。 いいえ
ポジショニング left/top/right/bottom オフセット。 いいえ
外観
注水 backgroundforegroundColor または Brush に対応)。 いいえ
枠線 borderWidthborderColorborderBrush いいえ
シェイプ shape いいえ - ただし、他のプロパティと組み合わせて使用します。clipborder は、この定義されたシェイプを使用します。
dropShadowinnerShadow いいえ
変換
グラフィック レイヤの空間移動 translationXtranslationYscaleX/YrotationX/Y/Z いいえ
管理 alphazIndex(スタッキング順序)、transformOrigin(ピボット ポイント) いいえ
タイポグラフィ
スタイル設定 textStylefontSizefontWeightfontStylefontFamily はい
色調 contentColorcontentBrush。これはアイコンのスタイル設定にも使用されます。 はい
段落 lineHeightletterSpacingtextAligntextDirectionlineBreakhyphens はい
デコレーション textDecorationtextIndentbaselineShift はい

スタイル パラメータを持つコンポーネントでスタイルを直接使用する

Style パラメータを公開するコンポーネントでは、スタイルを設定できます。

BaseButton(
    onClick = { },
    style = { }
) {
    BaseText("Click me")
}

スタイル ラムダ内で、externalPaddingbackground など、さまざまなプロパティを設定できます。

BaseButton(
    onClick = { },
    style = { background(Color.Blue) }
) {
    BaseText("Click me")
}

サポートされているプロパティの一覧については、スタイルで使用可能なプロパティ をご覧ください。

既存のパラメータがないコンポーネントに修飾子を使用してスタイルを適用する

組み込みのスタイル パラメータがないコンポーネントでも、styleable 修飾子を使用してスタイルを適用できます。この方法は、独自のカスタム コンポーネントを開発する場合にも便利です。

Row(
    modifier = Modifier.styleable { }
) {
    BaseText("Content")
}

style パラメータと同様に、ラムダ内に backgroundpadding などのプロパティを含めることができます。

Row(
    modifier = Modifier.styleable {
        background(Color.Blue)
    }
) {
    BaseText("Content")
}

複数のチェーン化された Modifier.styleable 修飾子は、適用されたコンポーザブルの継承されないプロパティに対して加算的であり、同じプロパティを定義する複数の修飾子と同様に動作します。継承されたプロパティの場合、これらはオーバーライドされ、チェーン内の最後の styleable 修飾子が値を設定します。

Modifier.styleable を使用する場合は、状態ベースのスタイルを適用するために、修飾子で使用する StyleState を作成して提供することもできます。詳細については、スタイルを使用した状態とアニメーションをご覧ください。

スタンドアロン スタイルを定義する

再利用できるように、スタンドアロン スタイルを定義できます。

val style = Style { background(Color.Blue) }

定義したスタイルは、コンポーザブルのスタイル パラメータに渡すか、Modifier.styleable を使用して渡すことができます。Modifier.styleable を使用する場合は、StyleState オブジェクトも作成する必要があります。StyleState については、状態と スタイルを使用したアニメーションのドキュメントで詳しく説明しています。

次の例は、コンポーネントの組み込みパラメータを使用して直接スタイルを適用する方法と、Modifier.styleable を使用してスタイルを適用する方法を示しています。

val style = Style { background(Color.Blue) }

// built in parameter
BaseButton(onClick = { }, style = style) {
    BaseText("Button")
}

// modifier styleable
val styleState = remember { MutableStyleState(null) }
Column(
    Modifier.styleable(styleState, style)
) {
    BaseText("Column content")
}

このスタイルを複数のコンポーネントに渡すこともできます。

val style = Style { background(Color.Blue) }

// built in parameter
BaseButton(onClick = { }, style = style) {
    BaseText("Button")
}
BaseText("Different text that uses the same style parameter", style = style)

// modifier styleable
val columnStyleState = remember { MutableStyleState(null) }
Column(
    Modifier.styleable(columnStyleState, style)
) {
    BaseText("Column")
}
val rowStyleState = remember { MutableStyleState(null) }
Row(
    Modifier.styleable(rowStyleState, style)
) {
    BaseText("Row")
}

複数のスタイル プロパティを追加する

各行に異なるプロパティを設定することで、複数のスタイル プロパティを追加できます。

BaseButton(
    onClick = { },
    style = {
        background(Color.Blue)
        contentPaddingStart(16.dp)
    }
) {
    BaseText("Button")
}

修飾子ベースのスタイル設定とは異なり、スタイル内のプロパティは加算的ではありません。スタイルは、1 つのスタイル ブロック内のプロパティのリストで最後に設定された値を取得します。次の例では、背景が 2 回設定されているため、TealColor が適用される背景になります。パディングの場合、contentPaddingTop は上部 パディングを contentPadding で設定された上部パディングをオーバーライドし、値を結合しません。

BaseButton(
    style = {
        background(Color.Red)
        // Background of Red is now overridden with TealColor instead
        background(TealColor)
        // All directions of padding are set to 64.dp (top, start, end, bottom)
        contentPadding(64.dp)
        // Top padding is now set to 16.dp, all other paddings remain at 64.dp
        contentPaddingTop(16.dp)
    },
    onClick = {
        //
    }
) {
    BaseText("Click me!")
}

2 つの背景色と 2 つの contentPadding オーバーライドが設定されたボタン
図 1.2 つの背景色が設定され、2 つの contentPadding がオーバーライドされたボタン。

複数のスタイル オブジェクトをマージする

複数のスタイル オブジェクトを作成して、コンポーザブルのスタイル パラメータに渡すことができます。

val style1 = Style { background(TealColor) }
val style2 = Style { contentPaddingTop(16.dp) }

BaseButton(
    style = style1 then style2,
    onClick = {

    },
) {
    BaseText("Click me!")
}

背景色と contentPaddingTop が設定されたボタン
図 2.背景色と contentPaddingTop が設定されたボタン。

複数のスタイルで同じプロパティが指定されている場合は、最後に設定されたプロパティが選択されます。スタイルではプロパティが加算的ではないため、最後に渡された パディングは、最初の contentPaddingによって設定されたcontentPaddingHorizontalをオーバーライドします。また、最後の背景色は、最初に渡されたスタイルで設定された背景色をオーバーライドします。

val style1 = Style {
    background(Color.Red)
    contentPadding(32.dp)
}

val style2 = Style {
    contentPaddingHorizontal(8.dp)
    background(Color.LightGray)
}

BaseButton(
    style = style1 then style2,
    onClick = {

    },
) {
    BaseText("Click me!")
}

この場合、適用されるスタイルは、左右のパディングを除き、ライトグレーの背景と 32.dp のパディングになります。左右のパディングの値は 8.dp です。

異なるスタイルでオーバーライドされた contentPadding を持つボタン
図 3.異なるスタイルでオーバーライドされた contentPadding を持つボタン。

スタイルの継承

contentColor やテキスト スタイル関連のプロパティなど、特定のスタイル プロパティは子コンポーザブルに伝播します。子コンポーザブルに設定されたスタイルは、その特定の子の継承された親のスタイルをオーバーライドします。

Style、styleable、direct パラメータによるスタイルの伝播
図 4.Stylestyleable、直接パラメータを使用したスタイルの伝播。
候補 メソッド エフェクト
1(最高) コンポーザブルの直接引数 すべてをオーバーライドします(例: Text(color = Color.Red))。
2 スタイル パラメータ ローカル スタイルは Text(style = Style { contentColor(Color.Red)} をオーバーライドします。
3 修飾子チェーン コンポーネント自体の Modifier.styleable{ contentColor(Color.Red)
4(最低) 親スタイル 親から渡される継承可能なプロパティ(タイポグラフィ/色)。

親のスタイル設定

親コンポーザブルからテキスト プロパティ(contentColor など)を設定すると、すべての子 Text コンポーザブルに伝播します。

val styleState = remember { MutableStyleState(null) }
Column(
    modifier = Modifier.styleable(styleState) {
        background(Color.LightGray)
        val blue = Color(0xFF4285F4)
        val purple = Color(0xFFA250EA)
        val colors = listOf(blue, purple)
        contentBrush(Brush.linearGradient(colors))
    },
) {
    BaseText("Children inherit", style = { width(60.dp) })
    BaseText("certain properties")
    BaseText("from their parents")
}

子コンポーザブルのプロパティ継承
図 5.子コンポーザブルのプロパティの継承。

子によるプロパティのオーバーライド

特定の Text コンポーザブルにスタイルを設定することもできます。親コンポーザブルにスタイルが設定されている場合、子コンポーザブルに設定されたスタイルは親コンポーザブルのスタイルをオーバーライドします。

val styleState = remember { MutableStyleState(null) }
Column(
    modifier = Modifier.styleable(styleState) {
        background(Color.LightGray)
        val blue = Color(0xFF4285F4)
        val purple = Color(0xFFA250EA)
        val colors = listOf(blue, purple)
        contentBrush(Brush.linearGradient(colors))
    },
) {
    BaseText("Children can ", style = {
        contentBrush(Brush.linearGradient(listOf(Color.Red, Color.Blue)))
    })
    BaseText("override properties")
    BaseText("set by their parents")
}

子コンポーザブルが親のプロパティをオーバーライドする
図 6.子コンポーザブルは親プロパティをオーバーライドします。

カスタム スタイル プロパティを実装する

次の例に示すように、StyleScope で拡張関数を使用すると、既存のスタイル定義にマッピングされるカスタム プロパティを作成できます。

fun StyleScope.outlinedBackground(color: Color) {
    border(1.dp, color)
    background(color)
}

スタイル定義内でこの新しいプロパティを適用します。

val customExtensionStyle = Style {
    outlinedBackground(Color.Blue)
}

新しいスタイル設定可能なプロパティの作成はサポートされていません。このようなサポートが必要な場合は、機能リクエストを送信してください。

CompositionLocal の値を読み取る

パラメータとして渡す必要なく変数にアクセスできるように、デザイン システム トークンを CompositionLocal に保存するのが一般的なパターンです。スタイルは CompositionLocal にアクセスして、スタイル内のシステム全体の値を取得できます。

val buttonStyle = Style {
    contentPadding(12.dp)
    shape(RoundedCornerShape(50))
    background(Brush.verticalGradient(LocalCustomColors.currentValue.background))
}