调整Jetpack Compose按钮中文本的位置居中

4
我目前正在开发一个按钮,它包含3个元素:一个图标(大小固定),一个标题(例如“立即购买!”)和商品价格。应显示的价格是自适应的,可能是 €2,00 或 €2000,00。标题应该基于按钮本身居中,而不是所占用的区域。
商品价格在按钮内具有优先级,并且始终应以设置的样式完全显示。因此,该对象的大小是可变的,不能预先确定。
当价格对象的长度增加时,标题的可用空间自然会减少。然而,在尝试居中文本时,我只能让它基于可用空间居中,这导致文本偏离中心。
如何解决这个问题,使文本基于父元素(按钮)居中,而不是基于可用文本大小?

你可以使用ConstraintLayout,尝试过了吗? - Vahid Garousi
我不知道Jetpack Compose有Constraintlayout,所以我会确保去了解一下。然而,我对XML也不是很熟悉,更不用说XML Constraintlayout和Jetpack Compose版本了。如果您有任何想法,可以给我提供一个(可能简化的)示例,我可以参考并自己实现! - Bart P
当然,稍等一下。 - Vahid Garousi
2个回答

3
我为您准备了一个易于理解的例子,如果有用,请选择我的答案作为正确答案。 enter image description here

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.AppBarDefaults
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.constraintlayout.compose.ConstraintSet
import androidx.constraintlayout.compose.Dimension
import stackoverflow.answers.ui.theme.StackOverflowAnswersTheme


@Composable
private fun StandardToolbar(
    onProfileButtonClick: () -> Unit,
    onFilterButtonClick: () -> Unit,
    onBackButtonClick: () -> Unit
) {
    val constraintSet = ConstraintSet {
        val startReference = createRefFor("startReference")
        val endReference = createRefFor("endReference")
        val titleReference = createRefFor("titleReference")
        constrain(startReference) {
            start.linkTo(parent.start, 16.dp)
            top.linkTo(parent.top, 16.dp)
            bottom.linkTo(parent.bottom, 16.dp)
            width = Dimension.value(48.dp)
        }
        constrain(endReference) {
            end.linkTo(parent.end, 16.dp)
            top.linkTo(parent.top, 16.dp)
            bottom.linkTo(parent.bottom, 16.dp)
            width = Dimension.value(48.dp)
        }
        constrain(titleReference) {
            start.linkTo(startReference.end, 8.dp)
            end.linkTo(endReference.start, 8.dp)
            top.linkTo(parent.top, 16.dp)
            bottom.linkTo(parent.bottom, 16.dp)
            width = Dimension.fillToConstraints
        }
    }
    Surface(
        elevation = AppBarDefaults.TopAppBarElevation,
        shape = RoundedCornerShape(
            bottomStart = 50f,
            bottomEnd = 50f
        ),
        color = Color(0XFF2F364E),
        modifier = Modifier
            .fillMaxWidth()
            .height(72.dp)
    ) {
        ConstraintLayout(
            modifier = Modifier.fillMaxSize(),
            constraintSet = constraintSet
        ) {
            Box(
                modifier = Modifier
                    .layoutId("startReference")
                    .size(48.dp)
                    .background(Color.Blue)
            ) {

            }
            Text(
                modifier = Modifier
                    .layoutId("titleReference"),
                text = "Title",
                style = MaterialTheme.typography.h5.copy(fontWeight = FontWeight.Bold),
                color = Color.White,
                overflow = TextOverflow.Ellipsis,
                textAlign = TextAlign.Center,
                maxLines = 1
            )
            Box(
                modifier = Modifier
                    .layoutId("endReference")
                    .size(48.dp)
                    .background(Color.Green)
            ) {
                Text(text = "E 20,000", modifier = Modifier.align(Alignment.Center), style = MaterialTheme.typography.caption)
            }
        }
    }
}


@Composable
@Preview
fun StandardToolbarPreview() {
    CompositionLocalProvider(
        LocalLayoutDirection provides LayoutDirection.Ltr
    ) {
        StackOverflowAnswersTheme {
            StandardToolbar(
                onProfileButtonClick = { },
                onFilterButtonClick = { },
                onBackButtonClick = {}
            )
        }
    }
}

感谢提供的示例!虽然它并没有完全实现我想要的功能,但它是一个有用的参考,展示了如何使用Constraintlayout! - Bart P

1
你可以试试这个:
Button(
    modifier = Modifier
      .wrapContentHeight()
      .padding(horizontal = 8.dp),
    onClick = {}
) {
      Row(
          modifier = Modifier.fillMaxWidth(),
          verticalAlignment = Alignment.CenterVertically,
          horizontalArrangement = Arrangement.SpaceAround
      ) {

           Box(
               modifier = Modifier.weight(1f),
               contentAlignment = Alignment.TopStart
           ) {
               Icon(
                  imageVector = Icons.Default.ImageSearch,
                  contentDescription = null
               )
           }

           Box(
               modifier = Modifier.weight(1f),
               contentAlignment = Alignment.Center
           ) {
               Text(
                     text = "Buy Now"
               )
           }

           Box(
                modifier = Modifier.weight(1f),
                contentAlignment = Alignment.TopEnd
           ) {
               Text(
                   text = "€ 2.00"
                 // text = "€ 2000.00"
               )
           }
       }
 }

enter image description here

有一个内容参数,您可以使用它来设置其内容,在这种情况下,我们使用Row将内容设置为水平轴。
请注意,每个组件Icon,TextText都包装在一个权重为1fBox中,使每个这些盒子作为其容器,也占据了父级Row的相等划分空间。
中间的Box将其子项定位在中心,而第一个和最后一个Box将其子项(即IconText)定位在TopStartTopEnd对齐方式,尽管您不需要担心“顶部”定位,因为父级Row将所有子项垂直居中对齐。
如果我们在每个Box上放置background颜色,
Modifier.background(Color.LightGray/Gray/DarkGray)

我们可以清楚地看到它们的等宽。

enter image description here


1
谢谢你的回答!我最终进行了一些修改,包括添加了一些额外的填充和文本溢出,但它确实完全符合我的要求! - Bart P

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