https://kotlinlang.org logo
Title
i

iroyo

04/18/2023, 3:35 PM
Hello everyone, How could I center / align the icon on the left to the middle of the first line (not the basline of the first line)? With one line is very easy but if you add more..
@Preview
@Preview(fontScale = 3f)
@Composable
fun TestCheckbox2() {
    Row(verticalAlignment = Alignment.CenterVertically) {
        Icon(
            painter = painterResource(id = R.drawable.ic_checkbox_checked), contentDescription = null,
        )
        Text(
            text = "Line 1\nline2",
        )
    }
}
I one to avoid using a constraint layout and add “invisible” lines to align it. First image what I have, second image what I want to achieve
t

Travis Griggs

04/18/2023, 4:17 PM
I'm sure there are better ways than what I'm proposing, but I'm pushing myself to contribute. It's a little unclear what your constraints are. Do you always have exactly two lines, or it varies? Cheesy solution 1:
@Preview
@Preview(fontScale = 3f)
@Composable
fun TestCheckbox3() {
   Column {
      Row(verticalAlignment = Alignment.CenterVertically) {
         Icon(Icons.Default.CheckBox, contentDescription = null)
         Text(text = "Line 1")
      }
      Row(verticalAlignment = Alignment.CenterVertically) {
         Icon(Icons.Default.CheckBox, contentDescription = null, modifier = Modifier.alpha(0f))
         Text(text = "line 2")
      }
   }
}
Assuming Solution 2:
@Preview
@Preview(fontScale = 3f)
@Composable
fun TestCheckbox4() {
   Row(modifier = Modifier.height(IntrinsicSize.Min), verticalAlignment = <http://Alignment.Top|Alignment.Top>) {
      Icon(
         Icons.Default.CheckBox,
         contentDescription = null,
         modifier = Modifier.fillMaxHeight(0.5f)
      )
      Text(text = "Line 1\nline2")
   }
}
I think there's a way to compose/align with virtual lines, but I haven't explored that yet. Hopefully my cheesy contributions will goad someone more experienced into giving a real solution 😄
e

efemoney

04/18/2023, 6:34 PM
Modifier.alignBy
on the icon &
Modifier.alignByBaseline
on the text.
Then you can tweak the position of the icon based on its size and the alignment line
e

ephemient

04/19/2023, 5:19 AM
Icon
doesn't emit alignment lines, so unfortunately
Modifier.alignByBaseline()
won't help
you can manually add alignment lines with a custom layout, but aligning by baseline doesn't center it anyway
a simple hack you can easily do, though:
Row {
    var firstLineHeight by remember { mutableStateOf(0f) }
    Icon(
        ...,
        modifier = Modifier.heightIn(min = with(LocalDensity.current) { firstLineHeight.toDp() })
    )
    Text(
        ...,
        onTextLayout = { firstLineHeight = it.getLineBottom(0) }
    )
}
o

Oleksandr Balan

04/19/2023, 5:46 AM
Your case is kinda similar to the recent article: https://link.medium.com/KVLIQrNk7yb Article reccomends to add an additional text composable. So I think you could simply wrap your Icon in the Box and place some Text there with an empty string.
Row {
    Box(contentAlignment = Alignment.Center) {
        Text(text = "")
        Icon(
            imageVector = Icons.Default.List,
            contentDescription = null,
        )
    }
    Text(
        text = "Line 1\nline2",
    )
}
i

iroyo

04/19/2023, 9:16 AM
yes this is what I’ll end up doing using a box. Thanks you all
e

ephemient

04/19/2023, 7:14 PM
even if two Text instances use the same TextStyle, it's possible for their font padding to be different depending on the characters in use (see https://medium.com/androiddevelopers/fixing-font-padding-in-compose-text-768cd232425b), so that doesn't seem like a reliable solution to me