Compose UI:FloatingActionButton

投稿日:  更新日:

Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。

そのライブラリ中のFloatingActionButtonについて、構成や使用方法などをまとめます。

※環境:Android Studio Koala | 2024.1.1
    Kotlin 1.9.0
    Compose Compiler 1.5.1
    androidx.compose.material3:material3 1.1.1

スポンサーリンク

UIの概要

FloatingActionButton(以下Fabと表現)はアプリ画面の最上位レイヤーに表示され、常に定位置に存在するボタンです。

アプリ画面の上に浮いて見えるため、「フローティング」と呼ばれます。

ボタン押下時の動作は、アプリ画面で最も重要な(頻度の多い)動作に割り当てます。

Scaffoldに組み込んで使用すると、アプリバーを避けて配置してくれるので便利です。

FloatingActionButtonの概要

Fabはマテリアルデザインの指標に準拠しています。

Material2までは円形でしたが、Material3からは角の丸い矩形になりました。
詳細は「マテリアルデザイン:Floating action buttons」を参照してください。

スポンサーリンク

関数の引数

Fabの状態(装飾、演出など)は、引数により指定できます。

@Composable
fun FloatingActionButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    shape: Shape = FloatingActionButtonDefaults.shape,
    containerColor: Color = FloatingActionButtonDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    content: @Composable () -> Unit,
) { ... }
引数概要
onClick,() -> Unitクリックで実行する関数オブジェクト
(ラムダ式)
modifierModifierUI全般のCompose修飾子
shapeShape角の形状
containerColorColorコンテナ(ボタン背景)の色
contentColorColorコンテンツの色
elevationFloatingActionButtonElevationボタンの高さ(影の広がりが変化)
interactionSourceMutableInteractionSourceユーザが行ったUI操作の観測と報告
content@Composable () -> Unitコンテンツのスロット
スポンサーリンク

関数の構成

FabはSurfaceとBoxを重ね合わせた構成になっています。

Fabの構成

Boxに格納されるcontentは中心に配置されます。

@Composable
fun FloatingActionButton(
    ...
    content: @Composable () -> Unit,
) {
    Surface(
        ...
    ) {
        CompositionLocalProvider(LocalContentColor provides contentColor) {
            ProvideTextStyle(
                MaterialTheme.typography.fromToken(ExtendedFabPrimaryTokens.LabelTextFont),
            ) {
                Box(
                    modifier = Modifier
                        .defaultMinSize(
                            minWidth = FabPrimaryTokens.ContainerWidth,
                            minHeight = FabPrimaryTokens.ContainerHeight,
                        ),
                    contentAlignment = Alignment.Center,
                ) { content() }
            }
        }
    }
}
スポンサーリンク

派生タイプ

FloatingActionButton関数をベースにした派生タイプが定義されています。

SmallFloatingActionButton

サイズが小さいFabです。

@Composable
fun FabPanel() {
    Box(modifier = Modifier.fillMaxSize()) {
        Column(
            verticalArrangement = Arrangement.spacedBy(16.dp)
        ) {
            for(i in 0..15) {
                Text(
                    modifier = Modifier.padding(start = 8.dp, end = 8.dp),
                    text = "スクロールアイテム(${i})"
                )
            }
        }
        SmallFloatingActionButton(
//        FloatingActionButton(
//        LargeFloatingActionButton(
            onClick = { /* クリック時の処理 */ },
            modifier = Modifier
                .align(alignment = Alignment.BottomEnd)
                .padding(15.dp),
            containerColor = MaterialTheme.colorScheme.primary,
            contentColor = MaterialTheme.colorScheme.onPrimary
        ) {
            Icon(Icons.Default.Add, contentDescription = "Add")
        }
    }
}

SmallFloatingActionButton

FloatingActionButton(ベース)

サイズがデフォルトのFabです。

FloatingActionButton(ベース)

LargeFloatingActionButton

サイズが大きいFabです。

LargeFloatingActionButton

ExtendedFloatingActionButton

コンテンツの幅に合わせて、サイズが拡張するFabです。

@Composable
fun FabPanel() {
    Box(modifier = Modifier.fillMaxSize()) {
        Column(
            verticalArrangement = Arrangement.spacedBy(16.dp)
        ) {
            for(i in 0..15) {
                Text(
                    modifier = Modifier.padding(start = 8.dp, end = 8.dp),
                    text = "スクロールアイテム(${i})"
                )
            }
        }
        ExtendedFloatingActionButton(
            onClick = { /* クリック時の処理 */ },
            modifier = Modifier
                .align(alignment = Alignment.BottomEnd)
                .padding(15.dp),
            containerColor = MaterialTheme.colorScheme.primary,
            contentColor = MaterialTheme.colorScheme.onPrimary
        ) {
            Icon(Icons.Default.Favorite, contentDescription = "Favorite")
            Spacer(modifier = Modifier.size(10.dp))
            Text(text = "Favorite")
//            Icon(Icons.Default.Edit, contentDescription = "Edit")
//            Spacer(modifier = Modifier.size(10.dp))
//            Text(text = "Edit")
        }
    }
}

ExtendedFloatingActionButton(拡張)

※フラグに応じて幅が伸縮するExtendedFloatingActionButtonは後述

スポンサーリンク

伸縮するFloattingActionButton

ExtendedFloatingActionButtonは拡張するタイプの他に、伸縮するタイプがあります。

コンテンツは「Text + Icon」の固定になりますが、フラグ(引数:expanded)により伸縮する機能が付加されています。

ExtendedFab(拡張)ExtendedFab(伸縮)
@Composable
fun ExtendedFloatingActionButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    shape: Shape = FloatingActionButtonDefaults.extendedFabShape,
    containerColor: Color = FloatingActionButtonDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    content: @Composable RowScope.() -> Unit,
) { ... }
@Composable
fun ExtendedFloatingActionButton(
    text: @Composable () -> Unit,
    icon: @Composable () -> Unit,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    expanded: Boolean = true,
    shape: Shape = FloatingActionButtonDefaults.extendedFabShape,
    containerColor: Color = FloatingActionButtonDefaults.containerColor,
    contentColor: Color = contentColorFor(containerColor),
    elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
) { ... }

この機能を使うと、「リストのスクロール中はFabを折り畳み、先頭・末尾にきたら展開」といったような、動きのあるFabが実装できます。

    Box(modifier = Modifier.fillMaxSize()) {
        val _scrollState = rememberScrollState()
        Column(
            modifier = Modifier.verticalScroll(_scrollState),
            verticalArrangement = Arrangement.spacedBy(16.dp)
        ) {
            for(i in 0..15) {
                Text(
                    modifier = Modifier.padding(start = 8.dp, end = 8.dp),
                    text = "スクロールアイテム(${i})"
                )
            }
        }
        val _listTop = _scrollState.value == 0
        val _listBottom = _scrollState.value == _scrollState.maxValue
        ExtendedFloatingActionButton(
            text = { Text(text = "Location") },
            icon = { Icon(Icons.Default.Place, contentDescription = "Location")},
            onClick = { /* クリック時の処理 */ },
            modifier = Modifier
                .align(alignment = Alignment.BottomEnd)
                .padding(15.dp),
            expanded = _listTop or _listBottom,
            containerColor = MaterialTheme.colorScheme.primary,
            contentColor = MaterialTheme.colorScheme.onPrimary
        )
    }
スポンサーリンク

elevationの働き

コンテナの色(containerColor)により、2通りの動作をします。

containerColor≒ColorScheme.surfaceの時

影の広がりが変わります。

@Composable
fun ElevationFabPanel() {
    Row {
        FloatingActionButton(
            onClick = { /* クリック時の処理 */ },
            modifier = Modifier.padding(15.dp),
            containerColor = MaterialTheme.colorScheme.primary,
            contentColor = MaterialTheme.colorScheme.onPrimary,
            elevation = FloatingActionButtonDefaults.elevation(
//                defaultElevation = 0.dp
				defaultElevation = 6.dp		// デフォルト
//                defaultElevation = 12.dp
            )
        ) { Icon(Icons.Default.Add, contentDescription = "Add") }
    }
}

containerColor≒ColorScheme.surfaceの時

containerColor=ColorScheme.surfaceの時

ColorScheme.surfaceに半透明なColorScheme.surfaceTintを重ね合わせた色になります。

その半透明の割合がelevationです。

@Composable
fun ElevationFabPanel() {
    Row {
        FloatingActionButton(
            onClick = { /* クリック時の処理 */ },
            modifier = Modifier.padding(15.dp),
            containerColor = MaterialTheme.colorScheme.surface,
            contentColor = MaterialTheme.colorScheme.onSurface,
            elevation = FloatingActionButtonDefaults.elevation(
//                defaultElevation = 0.dp
				defaultElevation = 6.dp		// デフォルト
//                defaultElevation = 12.dp
            )
        ) { Icon(Icons.Default.Add, contentDescription = "Add") }
    }
}

containerColor=ColorScheme.surfaceの時

これはSurface(Compose UI)が持つ機能です。

@Composable
private fun surfaceColorAtElevation(color: Color, elevation: Dp): Color {
    return if (color == MaterialTheme.colorScheme.surface) {
        MaterialTheme.colorScheme.surfaceColorAtElevation(elevation)
    } else {
        color
    }
}
fun ColorScheme.surfaceColorAtElevation(
    elevation: Dp,
): Color {
    if (elevation == 0.dp) return surface
    val alpha = ((4.5f * ln(elevation.value + 1)) + 2f) / 100f
    return surfaceTint.copy(alpha = alpha).compositeOver(surface)
}

この機能が、どのような場面で利用されるのか、不明です。利用価値はあるのでしょうか?!

スポンサーリンク

関連記事:

Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のButtonについて、構成や使用方法などをまとめます。 ※環境:Android Studio Flamingo | 2022.2.1    :androidx.compose.material3:material3:1.1.1    :androidx.compose.ui:ui:1.4.3 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のSurfaceについて、構成や使用方法などをまとめます。 ※環境:Android Studio Flamingo | 2022.2.1    :androidx.compose.material3:material3:1.1.1    :androidx.compose.ui:ui:1.4.3 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のRadioButtonについて、構成や使用方法などをまとめます。 ※環境:Android Studio Hedgehog | 2023.1.1     Kotlin 1.8.10     Compose Compiler 1.4.3 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中にUI要素を格納する機能をもつコンテナ型のUIがあります。 Column/Row/Boxがコンテナ型のUIです。構成や使用方法などをまとめます。 ※環境:Android Studio Hedgehog | 2023.1.1 Patch 1     Kotlin 1.8.10     Compose Compiler 1.4.3 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のImageについて、構成や使用方法などをまとめます。 ※環境:Android Studio Hedgehog | 2023.1.1 Patch 2     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation 1.5.0 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のDividerについて、構成や使用方法などをまとめます。 ※環境:Android Studio Hedgehog | 2023.1.1 Patch 2     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.material3:material3 1.1.1 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のSpacerについて、構成や使用方法などをまとめます。 ※環境:Android Studio Hedgehog | 2023.1.1 Patch 2     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation 1.5.0 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のSliderについて、構成や使用方法などをまとめます。 ※環境:Android Studio Hedgehog | 2023.1.1 Patch 2     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.material3:material3 1.1.1 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のScaffoldについて、構成や使用方法などをまとめます。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.material3:material3 1.1.1 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のTopAppBarについて、構成や使用方法などをまとめます。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.material3:material3 1.1.1 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のBottomAppBarについて、構成や使用方法などをまとめます。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.material3:material3 1.1.1 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のSnackbarについて、構成や使用方法などをまとめます。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.material3:material3 1.1.1 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のLazyColumnについて、構成や使用方法などをまとめます。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation:foundation 1.6.8 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のLazyRowについて、構成や使用方法などをまとめます。 ※環境:Android Studio Koala | 2024.1.1 Patch 1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation:foundation 1.6.8 ...
スポンサーリンク