Beispiele mit Stilen

In der folgenden Dokumentation finden Sie Beispiele für die Verwendung von Stilen zum Erstellen bestimmter Arten von Komponenten.

Schaltflächen

Mit Stilen lassen sich viele verschiedene Arten von Schaltflächen erstellen, die sich von den Standard-Material-Komponenten unterscheiden können.

Basistaste

Betrachten Sie die folgende Schaltfläche, die als Grundlage für verschiedene Arten von Schaltflächen dient:

@Composable
fun BaseButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    style: Style = Style,
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource? = null,
    content: @Composable RowScope.() -> Unit
) {
    val effectiveInteractionSource = interactionSource ?: remember {
        MutableInteractionSource()
    }
    val styleState = remember(effectiveInteractionSource) {
        MutableStyleState(effectiveInteractionSource)
    }
    styleState.isEnabled = enabled
    Row(
        modifier = modifier
            .semantics(properties = {
                role = Role.Button
            })
            .clickable(
                enabled = enabled,
                onClick = onClick,
                interactionSource = effectiveInteractionSource,
                indication = null,
            )
            .styleable(styleState, baseButtonStyle, style),
        content = content,
        verticalAlignment = Alignment.CenterVertically
    )
}

Mouseover-Hintergrund für Übersetzungsschaltfläche

Mit dem folgenden Code können Sie eine Schaltfläche mit einem Hintergrund definieren, der sich beim Hovern bewegt:

Abbildung 1. Schaltfläche mit Hintergrund, der beim Hovern übersetzt wird.

@Preview
@Composable
fun HoverButtonExample() {
    Box(
        modifier = Modifier.padding(32.dp),
        contentAlignment = Alignment.Center
    ) {
        BaseButton(
            onClick = {},
            style = Style {
                background(Color.Transparent)
                shape(RoundedCornerShape(0.dp))
                border(1.dp, Color.Black)
                contentColor(Color.Black)
                fontSize(16.sp)
                fontWeight(FontWeight.Light)
                letterSpacing(1.sp)
                contentPadding(vertical = 13.dp, horizontal = 20.dp)
                dropShadow(
                    Shadow(
                        spread = 0.dp, color = Color(0xFFFFE54C),
                        radius = 0.dp,
                        offset = DpOffset(7.dp, 7.dp)
                    )
                )
                hovered {
                    animate(tween(200)) {
                        dropShadow(
                            Shadow(
                                spread = 0.dp, color = Color(0xFFFFE54C),
                                radius = 0.dp,
                                offset = DpOffset(0.dp, 0.dp)
                            )
                        )
                    }
                }
                pressed {
                    animate(tween(200)) {
                        dropShadow(
                            Shadow(
                                spread = 0.dp, color = Color(0xFFFFE54C),
                                radius = 0.dp,
                                offset = DpOffset(0.dp, 0.dp)
                            )
                        )
                    }
                }
            }
        ) {
            BaseText("Button 52")
        }
    }
}

Abgerundete Schaltfläche mit Tiefeneffekt und Schattenanimation

So erstellen Sie eine Schaltfläche mit einem Tiefeneffekt, bei dem der Schatten auf pressed nach oben und unten verschoben wird:

Abbildung 2. Schaltfläche mit Tiefeneffekt, bei der die Schattenebene beim Drücken verschoben wird.

@Preview
@Composable
fun ShadowAnimationButton() {
    Box(modifier = Modifier.padding(32.dp)) {
        val density = LocalDensity.current
        val buttonStyle = Style {
            background(Color(0xFFFBEED0))
            border(2.dp, Color(0xFF422800))
            shape(RoundedCornerShape(30.dp))
            dropShadow(
                Shadow(
                    color = Color(0xFF422800), offset = DpOffset(4.dp, 4.dp),
                    radius = 0.dp, spread = 0.dp
                )
            )
            contentColor(Color(0xFF422800))
            fontWeight(FontWeight.SemiBold)
            fontSize(18.sp)
            contentPaddingHorizontal(25.dp)
            externalPadding(8.dp)
            height(50.dp)
            textAlign(TextAlign.Center)
            hovered {
                animate {
                    background(Color.White)
                }
            }
            pressed {
                animate {
                    dropShadow(
                        Shadow(
                            color = Color(0xFF422800),
                            offset = DpOffset(2.dp, 2.dp),
                            radius = 0.dp,
                            spread = 0.dp
                        )
                    )
                    translation(with(density) { 2.dp.toPx() }, with(density) { 2.dp.toPx() })
                }
            }
        }
        BaseButton(
            onClick = {},
            style = buttonStyle
        ) {
            BaseText("Button 74")
        }
    }
}

Mehrere überlagerte Stile mit gedrückter Animation

Mit dem folgenden Code wird eine Schaltfläche mit einem 3D-Effekt erstellt, der durch Styles mit mehreren Style-Ebenen erzielt wird, die alle denselben StyleState verwenden:

Abbildung 3. Schaltfläche mit Tiefeneffekt und mehreren Stilebenen.

@Preview
@Composable
fun MultipleStylesButton() {
    val interactionSource = remember { MutableInteractionSource() }
    val styleState = remember(interactionSource) { MutableStyleState(interactionSource) }
    val density = LocalDensity.current

    Box(
        modifier = Modifier
            .styleable(styleState) {
                size(200.dp, 48.dp)
                externalPadding(32.dp)
            }
            .clickable(interactionSource, indication = null) {},
        contentAlignment = Alignment.Center
    ) {
        val edgeStyle = Style {
            fillSize()
            shape(RoundedCornerShape(16.dp))
            background(Color(0xFF1CB0F6))
        }

        val frontStyle = Style {
            fillSize()
            background(Color(0xFF1899D6))
            shape(RoundedCornerShape(16.dp))
            contentPadding(vertical = 12.dp, horizontal = 16.dp)
            translationY(with(density) { (-4).dp.toPx() })
            pressed {
                animate {
                    translationY(with(density) { (0).dp.toPx() })
                }
            }
        }
        Box(modifier = Modifier.semantics(properties = {
            role = Role.Button
        }).styleable(styleState, edgeStyle)) {
            Box(
                modifier = Modifier
                    .styleable(styleState, frontStyle),
                contentAlignment = Alignment.Center
            ) {
                BaseText(
                    "Button 19".toUpperCase(Locale.current),
                    style = Style {
                        contentColor(Color.White)
                        fontSize(15.sp)
                        fontWeight(FontWeight.Bold)
                        letterSpacing(0.8.sp)
                    }
                )
            }
        }
    }
}

Schaltfläche für den Effekt „Farbverlauf“

Wenn Sie einen Farbverlaufseffekt erzielen möchten, der unendlich animiert wird, können Sie Stile in Kombination mit rememberInfiniteTransition verwenden:

Abbildung 4. Schaltfläche für den Effekt „Farbverlauf-Leuchten“.

@Preview
@Composable
fun GradientGlowButtonExample() {
    val infiniteTransition = rememberInfiniteTransition(label = "glowing_button_85_animation")
    val animatedProgress by infiniteTransition.animateFloat(
        initialValue = 0f,
        targetValue = 1f,
        animationSpec = infiniteRepeatable(
            animation = tween(durationMillis = 20000, easing = LinearEasing),
        ), label = "progress"
    )

    val gradientColors = listOf(
        Color(0xffff0000), Color(0xffff7300), Color(0xfffffb00), Color(0xff48ff00),
        Color(0xff00ffd5), Color(0xff002bff), Color(0xff7a00ff), Color(0xffff00c8),
        Color(0xffff0000)
    )

    val glowingBrush = remember(animatedProgress) {
        object : ShaderBrush() {
            override fun createShader(size: Size): Shader {
                val width = size.width * 4
                val brushSize = width * animatedProgress
                return LinearGradientShader(
                    colors = gradientColors,
                    from = Offset(brushSize, 0f),
                    to = Offset(brushSize + width, 0f),
                    tileMode = TileMode.Repeated
                )
            }
        }
    }


    Box(
        modifier = Modifier
            .padding(32.dp),
        contentAlignment = Alignment.Center
    ) {
        BaseButton(
            onClick = { },
            style = Style {
                dropShadow(
                    Shadow(
                        brush = glowingBrush,
                        radius = 5.dp
                    )
                )
                transformOrigin(TransformOrigin.Center)
                pressed {
                    animate {
                        dropShadow(
                            Shadow(
                                brush = glowingBrush,
                                radius = 10.dp
                            )
                        )
                        scale(0.95f)
                    }

                }
                size(width = 200.dp, height = 50.dp)
                background(Color(0xFF111111))
                shape(RoundedCornerShape(10.dp))
                contentColor(Color.White)
                contentPadding(vertical = (0.6f * 14).dp, horizontal = (2f * 14).dp)
                border(width = 0.dp, color = Color.Transparent)
            }
        ) {
            BaseText(text = "Button 85")
        }
    }
}