JetPack Compose 带有可绘制对象的按钮

10

我们如何在Jetpack Compose中实现这个功能

enter image description here

我正在做类似这样的事情

Button(
    elevation = ButtonDefaults.elevation(
        defaultElevation = 0.dp,
        pressedElevation = 8.dp,
        disabledElevation = 0.dp
    ),
    onClick = { onClick },
    shape = RoundedCornerShape(28.dp),
    modifier = modifier
        .fillMaxWidth()
        .shadow(0.dp),
    contentPadding = PaddingValues(15.dp),
    colors = ButtonDefaults.buttonColors(backgroundColor = Color.White),
    border = BorderStroke(1.dp, Color.Grey)
) {
    Box(modifier = modifier.fillMaxWidth(),
        contentAlignment = Alignment.Center) {
        Icon(
            imageVector = imageVector,
            modifier = Modifier
                .size(18.dp),
            contentDescription = "drawable icons",
            tint = Color.Unspecified
        )
        Spacer(modifier = Modifier.width(10.dp))
        Text(
            text = buttonText,
            color = Color.Black,
            textAlign = TextAlign.Center
        )
    }
}

enter image description here

正如您所看到的,Google徽标位于我需要它在盒子开头的文本左侧,那么我该如何做呢?


谢谢,我已经等了比你想象的更久时间来等待一个明智的问题。 - Richard Onslow Roper
1
尝试在图标中添加 Modifier.align(Alignment.CenterStart),并在 Text 中添加 Modifier.align(Alignment.Center) - ADM
无法工作,抛出所需的错误:Alignment.Vertical。 - Dheeraj Gupta
@DheerajGupta 你确定你仍在使用 Box 而不是下面答案中建议的 Row 吗?当你需要将一个项目居中布局,另一个项目放在某个侧面/角落时,使用 Box 是正确的方法。此外,你也可以安全地删除 Spacer,因为它对 Box 没有影响。 - Phil Dukhov
你说什么,“Pylyp”? - Richard Onslow Roper
6个回答

8
建议您可以使用Box将内容包装起来。
作为替代方案,您也可以直接使用ButtonRowScope,不需要任何容器。
只需对Text应用weight(1f)修饰符,并应用offset(x=- iconWidth/2)即可。
类似于以下代码:
Button(
   //....
) {

    Icon(
        imageVector = imageVector,
        modifier = Modifier.size(iconWidth),
        contentDescription = "drawable icons",
        tint = Color.Unspecified
    )
    Text(
        text = "Button",
        color = Color.Black,
        textAlign = TextAlign.Center,
        modifier = Modifier
            .weight(1f)
            .offset(x= -iconWidth/2) //default icon width = 24.dp
    )
}

enter image description here

如果您想使用一个 Box,请删除在 Box 中的 contentAlignment = Alignment.Center,并使用以下内容:
 Box(modifier = Modifier.fillMaxWidth()) {
        Icon( /* ..... */ )
        Text(
            modifier = Modifier.fillMaxWidth(),
            text = "buttonText",
            textAlign = TextAlign.Center
        )
 }

enter image description here


7
@Composable
fun GoogleButton(
    modifier: Modifier = Modifier,
    imageVector: ImageVector,
    buttonText: String,
    onClick: (isEnabled: Boolean) -> Unit = {},
    enable: Boolean = true,
    backgroundColor: Color,
    fontColor: Color,
) {
    Button(
        onClick = { onClick(enable) },
        modifier = modifier
            .fillMaxWidth()
            .shadow(0.dp)
            .noInteractionClickable(enabled = false) { onClick(enable) },
        elevation = ButtonDefaults.elevation(
            defaultElevation = 0.dp,
            pressedElevation = 0.dp,
            hoveredElevation = 0.dp,
            focusedElevation = 0.dp
        ),
        shape = RoundedCornerShape(28.dp),
        contentPadding = PaddingValues(15.dp),
        colors = ButtonDefaults.buttonColors(
            backgroundColor = backgroundColor,
            contentColor = fontColor
        ),
        border = BorderStroke(1.dp, MaterialTheme.colors.getButtonBorderStroke)
    ) {
        Box(
            modifier = Modifier
                .fillMaxWidth(),
            contentAlignment = Alignment.Center
        ) {
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .align(Alignment.CenterStart)
            ) {
                Spacer(modifier = Modifier.width(4.dp))
                Icon(
                    imageVector = imageVector,
                    modifier = Modifier
                        .size(18.dp),
                    contentDescription = "drawable_icons",
                    tint = Color.Unspecified
                )
            }
            Text(
                modifier = Modifier.align(Alignment.Center),
                text = buttonText,
                color = MaterialTheme.colors.loginButtonTextColor,
                textAlign = TextAlign.Center,
                fontSize = 16.sp,
                fontFamily = FontFamily(
                    Font(
                        R.font.roboto_medium
                    )
                )
            )
        }
    }
}

一个仅包含代码的答案并不是高质量的。虽然这段代码可能有用,但你可以通过解释它为什么有效、如何工作、何时应该使用以及其限制是什么来改进它。请编辑您的答案,包括解释和相关文档链接。 - Cliff Burton

4
您可以在IconModifier参数上使用align(Alignment.CenterStart),使图标在Box Composable的开始位置居中。这种对齐方式将优先于Box的对齐参数。
您还可以删除Spacer Composable,因为Box布局的子项按照组合顺序堆叠在一起。 因此,Spacer Composable实际上位于中心的Text Composable下方。
如果您想在IconText之间添加一些间隔,可以在Icon周围使用一些填充。
尝试以下方法(对我有效):
Box(modifier = modifier.fillMaxWidth(),
        contentAlignment = Alignment.Center) {
        Icon(
            imageVector = imageVector,
            modifier = Modifier
                .size(18.dp)
                .align(Alignment.CenterStart),
            contentDescription = "drawable icons",
            tint = Color.Unspecified
        )
        Text(
            text = buttonText,
            color = Color.Black,
            textAlign = TextAlign.Center
        )
    }

1

Box 不提供边界,因此对于较长的文本,它会导致重叠。 Row 对我来说效果更好。此外,您可以在这里使用 Spacer,而这对于 Box 是不可能的。在我的情况下,我已经使用 spacedBy 代替了 Spacer

Row(
    modifier = Modifier.fillMaxWidth(),
    horizontalArrangement = Arrangement.spacedBy(16.dp),
    verticalAlignment = Alignment.CenterVertically
) {
    Icon(
        painter,
        contentDescription = null
    )
    Box(
        modifier = Modifier.weight(1F),
        contentAlignment = Alignment.Center
    ) {
        Text(buttonText)
    }
}

0
如果你想要的话,我可以自己实现。
@Composable

fun GButton() {
val sourceImage = painterResource(id = R.drawable.ic_google)

OutlinedButton(
    onClick = { /*TODO*/ }) {
    Row(
        verticalAlignment = androidx.compose.ui.Alignment.CenterVertically,
        modifier = Modifier.padding(horizontal = 10.dp),
    ) {
        Image(sourceImage, contentDescription = "Google Logo")
        Spacer(modifier = Modifier.width(5.dp))
        Text(
            modifier = Modifier.fillMaxWidth(),
            textAlign = TextAlign.Center,
            text = "Continue with Google",
            color = Color.Black
        )
    }

}

}


-2
Box(contentAlignment = Center){
  Icon(Modifier.align(CenterStart))

  Text()
}

如果我使用了“spaceBetween”属性,那么文本就会向右对齐而不是居中。我已经尝试过居中对齐,但不起作用。 - Dheeraj Gupta
1
你在说什么? - Richard Onslow Roper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接