具有渐变背景的 Jetpack Compose 按钮?
Jetpack Compose Button with gradient background?
是否可以创建具有渐变背景的按钮?
@Composable
fun GradientButtonExample() {
val horizontalGradientBrush = Brush.horizontalGradient(
colors = listOf(
Color(0xffF57F17),
Color(0xffFFEE58),
Color(0xffFFF9C4)
)
)
val verticalGradientBrush = Brush.verticalGradient(
colors = listOf(
Color(0xff4E342E),
Color(0xff8D6E63),
Color(0xffD7CCC8)
)
)
Button(onClick = {}) {
Text(
text = "Horizontal Gradient",
modifier = Modifier
.background(brush = horizontalGradientBrush)
)
}
Button(onClick = {}) {
Text(
text = "Vertical Gradient",
modifier = Modifier
.background(brush = verticalGradientBrush)
)
}
}
使用 background(brush)
向 Text
添加渐变会在 Button
和 Text
之间留下空白。当我用 modifier.background(brush = horizontalGradientBrush)
设置按钮的背景时, Button
是用原色绘制的,基本上没有任何反应。是否可以设置 Button
的背景,而不是其他组件的渐变颜色?
实际上,您不需要按钮...您可以使用简单的 Text
...
来实现此结果
Text(
text = "Click Me",
style = TextStyle(color = Color.White),
modifier = Modifier
.clickable(onClick = {})
.background(
Brush.verticalGradient(
colors = listOf(
Color.Blue,
Color.Green
)
),
shape = RoundedCornerShape(4.dp)
)
.padding(horizontal = 16.dp, vertical = 8.dp),
)
编写 1.0.0-alpha10
你可以这样做:
@Composable
fun GradientButton(
text: String,
gradient : Brush,
modifier: Modifier = Modifier,
onClick: () -> Unit = { },
) {
Button(
modifier = modifier,
colors = ButtonDefaults.buttonColors(backgroundColor = Color.Transparent),
contentPadding = PaddingValues(),
onClick = { onClick() },
) {
Box(
modifier = Modifier
.background(gradient)
.then(modifier),
contentAlignment = Alignment.Center,
) {
Text(text = text)
}
}
}
用法示例:
@Composable
private fun Content() {
val gradient =
Brush.horizontalGradient(listOf(Color(0xFF28D8A3), Color(0xFF00BEB2)))
Column {
GradientButton(
text = "Gradient Button - Max Width",
gradient = gradient,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp)
)
GradientButton(
text = "Gradient Button - Wrap Width",
gradient = gradient,
modifier = Modifier
.wrapContentWidth()
.padding(horizontal = 16.dp, vertical = 8.dp)
)
}
}
结果样本:
Jetpack Compose 在创建 Button 或任何其他组件方面非常灵活,基本上 Button
是 Row
在 Surface
中,内容填充为
private val ButtonHorizontalPadding = 16.dp
private val ButtonVerticalPadding = 8.dp
因此可以将内边距设置为 0 并在为 Text
设置渐变背景后设置内边距,如下面的代码片段所示。
Button(contentPadding = PaddingValues(0.dp), onClick = {}) {
Text(
text = "Vertical Gradient",
modifier = Modifier
.preferredHeight(ButtonDefaults.MinHeight)
.align(Alignment.CenterVertically)
.background(brush = verticalGradientBrush)
.padding(8.dp)
)
}
基于默认 Button 可组合项及其所有参数和自定义选项的实现。
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun GradientButton(
onClick: () -> Unit,
gradient: Brush,
modifier: Modifier = Modifier,
enabled: Boolean = true,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
elevation: ButtonElevation? = ButtonDefaults.elevation(),
shape: Shape = MaterialTheme.shapes.small,
border: BorderStroke? = null,
contentColor: Color = MaterialTheme.colors.onSurface,
disabledContentColor: Color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled),
disabledBackgroundColor: Color = MaterialTheme.colors.onSurface.copy(alpha = 0.12f)
.compositeOver(MaterialTheme.colors.surface),
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
content: @Composable RowScope.() -> Unit
) {
val actualElevation = elevation?.elevation(enabled, interactionSource)?.value ?: 0.dp
val actualContentColor = if (enabled) contentColor else disabledContentColor
val background = if (enabled) {
Modifier.background(brush = gradient)
} else {
Modifier.background(color = disabledBackgroundColor)
}
Surface(
modifier = modifier
.shadow(actualElevation, shape, true)
.then(background),
shape = shape,
color = Color.Transparent,
contentColor = actualContentColor.copy(alpha = 1f),
border = border,
elevation = 0.dp,
onClick = onClick,
enabled = enabled,
role = Role.Button,
interactionSource = interactionSource,
indication = rememberRipple()
) {
CompositionLocalProvider(LocalContentAlpha provides actualContentColor.alpha) {
ProvideTextStyle(
value = MaterialTheme.typography.button
) {
Row(
Modifier
.defaultMinSize(
minWidth = ButtonDefaults.MinWidth,
minHeight = ButtonDefaults.MinHeight
)
.padding(contentPadding),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
content = content
)
}
}
}
}
Example screenshot with and without Modifier.fillMaxWidth
最灵活的方法是使用 TextButton
和 Modifier.drawBehind()
。
TextButton
不绘制任何自己的背景,但表现得像一个按钮。
Modifier.drawBehind()
让您可以完全控制要绘制的内容:渐变、几何形状等。
TextButton(modifier = Modifier.drawBehind { }) {
Text("Help")
}
我创建了一个框作为可点击元素的背景。然后给它添加修改器.background,带笔刷+水平渐变,作为参数。
Box(contentAlignment = Alignment.Center,
modifier = Modifier
.background(
brush = Brush.horizontalGradient(
listOf(Color.Red, Color.Green, Color.Blue),
10.0f,
20.0f
), shape = CircleShape
)
GradientButton 文件如下:
@Composable
fun GradientButton(
text: String,
textColor: Color,
gradient: Brush,
onClick: () -> Unit
) {
Button(
colors = ButtonDefaults.buttonColors(
backgroundColor = Color.Transparent
),
contentPadding = PaddingValues(),
onClick = { onClick() })
{
Box(
modifier = Modifier
.background(gradient)
.padding(horizontal = 16.dp, vertical = 8.dp),
contentAlignment = Alignment.Center
) {
Text(text = text, color = textColor)
}
}
}
MainActivity.kt 文件
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
// Row is used for align the buttons in center of screen
Row(
modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
// this is the first button
GradientButton(
text = "Button1", textColor = Color.Black, gradient = Brush.horizontalGradient(
colors = listOf(
c1,
c2,
c1
)
)
) {}
// Spacer is used to give the space between two buttons
Spacer(modifier = Modifier.width(10.dp))
// This is second button
GradientButton(
text = "Button2", textColor = Color.Black, gradient = Brush.horizontalGradient(
colors = listOf(
c3,
c4,
c3
)
)
) {}
}
}
}
}
Color.kt 文件
[val c1 = Color(0xFFE9F190)
val c2 = Color(0xFFF5DB0B)
val c3 = Color(0xFFF79F1E)
val c4 = Color(0xFFFF5722)
输出:
是否可以创建具有渐变背景的按钮?
@Composable
fun GradientButtonExample() {
val horizontalGradientBrush = Brush.horizontalGradient(
colors = listOf(
Color(0xffF57F17),
Color(0xffFFEE58),
Color(0xffFFF9C4)
)
)
val verticalGradientBrush = Brush.verticalGradient(
colors = listOf(
Color(0xff4E342E),
Color(0xff8D6E63),
Color(0xffD7CCC8)
)
)
Button(onClick = {}) {
Text(
text = "Horizontal Gradient",
modifier = Modifier
.background(brush = horizontalGradientBrush)
)
}
Button(onClick = {}) {
Text(
text = "Vertical Gradient",
modifier = Modifier
.background(brush = verticalGradientBrush)
)
}
}
使用 background(brush)
向 Text
添加渐变会在 Button
和 Text
之间留下空白。当我用 modifier.background(brush = horizontalGradientBrush)
设置按钮的背景时, Button
是用原色绘制的,基本上没有任何反应。是否可以设置 Button
的背景,而不是其他组件的渐变颜色?
实际上,您不需要按钮...您可以使用简单的 Text
...
Text(
text = "Click Me",
style = TextStyle(color = Color.White),
modifier = Modifier
.clickable(onClick = {})
.background(
Brush.verticalGradient(
colors = listOf(
Color.Blue,
Color.Green
)
),
shape = RoundedCornerShape(4.dp)
)
.padding(horizontal = 16.dp, vertical = 8.dp),
)
编写 1.0.0-alpha10
你可以这样做:
@Composable
fun GradientButton(
text: String,
gradient : Brush,
modifier: Modifier = Modifier,
onClick: () -> Unit = { },
) {
Button(
modifier = modifier,
colors = ButtonDefaults.buttonColors(backgroundColor = Color.Transparent),
contentPadding = PaddingValues(),
onClick = { onClick() },
) {
Box(
modifier = Modifier
.background(gradient)
.then(modifier),
contentAlignment = Alignment.Center,
) {
Text(text = text)
}
}
}
用法示例:
@Composable
private fun Content() {
val gradient =
Brush.horizontalGradient(listOf(Color(0xFF28D8A3), Color(0xFF00BEB2)))
Column {
GradientButton(
text = "Gradient Button - Max Width",
gradient = gradient,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp)
)
GradientButton(
text = "Gradient Button - Wrap Width",
gradient = gradient,
modifier = Modifier
.wrapContentWidth()
.padding(horizontal = 16.dp, vertical = 8.dp)
)
}
}
结果样本:
Jetpack Compose 在创建 Button 或任何其他组件方面非常灵活,基本上 Button
是 Row
在 Surface
中,内容填充为
private val ButtonHorizontalPadding = 16.dp
private val ButtonVerticalPadding = 8.dp
因此可以将内边距设置为 0 并在为 Text
设置渐变背景后设置内边距,如下面的代码片段所示。
Button(contentPadding = PaddingValues(0.dp), onClick = {}) {
Text(
text = "Vertical Gradient",
modifier = Modifier
.preferredHeight(ButtonDefaults.MinHeight)
.align(Alignment.CenterVertically)
.background(brush = verticalGradientBrush)
.padding(8.dp)
)
}
基于默认 Button 可组合项及其所有参数和自定义选项的实现。
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun GradientButton(
onClick: () -> Unit,
gradient: Brush,
modifier: Modifier = Modifier,
enabled: Boolean = true,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
elevation: ButtonElevation? = ButtonDefaults.elevation(),
shape: Shape = MaterialTheme.shapes.small,
border: BorderStroke? = null,
contentColor: Color = MaterialTheme.colors.onSurface,
disabledContentColor: Color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled),
disabledBackgroundColor: Color = MaterialTheme.colors.onSurface.copy(alpha = 0.12f)
.compositeOver(MaterialTheme.colors.surface),
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
content: @Composable RowScope.() -> Unit
) {
val actualElevation = elevation?.elevation(enabled, interactionSource)?.value ?: 0.dp
val actualContentColor = if (enabled) contentColor else disabledContentColor
val background = if (enabled) {
Modifier.background(brush = gradient)
} else {
Modifier.background(color = disabledBackgroundColor)
}
Surface(
modifier = modifier
.shadow(actualElevation, shape, true)
.then(background),
shape = shape,
color = Color.Transparent,
contentColor = actualContentColor.copy(alpha = 1f),
border = border,
elevation = 0.dp,
onClick = onClick,
enabled = enabled,
role = Role.Button,
interactionSource = interactionSource,
indication = rememberRipple()
) {
CompositionLocalProvider(LocalContentAlpha provides actualContentColor.alpha) {
ProvideTextStyle(
value = MaterialTheme.typography.button
) {
Row(
Modifier
.defaultMinSize(
minWidth = ButtonDefaults.MinWidth,
minHeight = ButtonDefaults.MinHeight
)
.padding(contentPadding),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
content = content
)
}
}
}
}
Example screenshot with and without Modifier.fillMaxWidth
最灵活的方法是使用 TextButton
和 Modifier.drawBehind()
。
TextButton
不绘制任何自己的背景,但表现得像一个按钮。
Modifier.drawBehind()
让您可以完全控制要绘制的内容:渐变、几何形状等。
TextButton(modifier = Modifier.drawBehind { }) {
Text("Help")
}
我创建了一个框作为可点击元素的背景。然后给它添加修改器.background,带笔刷+水平渐变,作为参数。
Box(contentAlignment = Alignment.Center,
modifier = Modifier
.background(
brush = Brush.horizontalGradient(
listOf(Color.Red, Color.Green, Color.Blue),
10.0f,
20.0f
), shape = CircleShape
)
GradientButton 文件如下:
@Composable
fun GradientButton(
text: String,
textColor: Color,
gradient: Brush,
onClick: () -> Unit
) {
Button(
colors = ButtonDefaults.buttonColors(
backgroundColor = Color.Transparent
),
contentPadding = PaddingValues(),
onClick = { onClick() })
{
Box(
modifier = Modifier
.background(gradient)
.padding(horizontal = 16.dp, vertical = 8.dp),
contentAlignment = Alignment.Center
) {
Text(text = text, color = textColor)
}
}
}
MainActivity.kt 文件
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
// Row is used for align the buttons in center of screen
Row(
modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
// this is the first button
GradientButton(
text = "Button1", textColor = Color.Black, gradient = Brush.horizontalGradient(
colors = listOf(
c1,
c2,
c1
)
)
) {}
// Spacer is used to give the space between two buttons
Spacer(modifier = Modifier.width(10.dp))
// This is second button
GradientButton(
text = "Button2", textColor = Color.Black, gradient = Brush.horizontalGradient(
colors = listOf(
c3,
c4,
c3
)
)
) {}
}
}
}
}
Color.kt 文件
[val c1 = Color(0xFFE9F190)
val c2 = Color(0xFFF5DB0B)
val c3 = Color(0xFFF79F1E)
val c4 = Color(0xFFFF5722)
输出: