https://kotlinlang.org logo
#compose
Title
# compose
g

Grigorii Yurkov

10/27/2020, 7:47 PM
How to center text vertically?
Copy code
Text(
                text = money,
                modifier = Modifier
                        .weight(.3f)
                        .wrapContentWidth(Alignment.End)
                        .wrapContentHeight(Alignment.CenterVertically),
                fontSize = 12.sp
        )
a

alorma

10/27/2020, 7:48 PM
Wrap it (and icon) in a
Row
and use
verticalAlignement
g

Grigorii Yurkov

10/27/2020, 7:51 PM
Ok, it will work for me, but this will put all elements in a row at center. And what if I don't want
s

Siyamed

10/27/2020, 7:51 PM
the code shared looks correct, there was a recent change related to width and height of text that we reverted. The code should work with next alpha release.
👌 1
p

P.J.

10/27/2020, 8:30 PM
sorry for thread hijack, but is there something like android:ems planned for TextField?@Siyamed
s

Siyamed

10/27/2020, 8:58 PM
For the width no, but it already is supported in TextUnit.Em
For the text size
It doesnt exists for the width of the components (textfield or text width / height)
p

P.J.

10/27/2020, 9:04 PM
aight, yea had the component width in mind. would be neat to be able to set the field width, so that exactly n-character fit in it. Or even so that it scales the width depending on the current value. 🙂
s

Siyamed

10/27/2020, 9:35 PM
You can do that actually buy listening to text layout changes. I believe BaseTextField have onTextLayout caplnlback that gives the size, intrinsics of text.
z

Zach Klippenstein (he/him) [MOD]

10/27/2020, 10:40 PM
wouldn’t that technique delay the text resize by a frame?
s

Siyamed

10/27/2020, 10:40 PM
OnTextLayout is called during layout, as far as i know it doesnt delay
Recently used it in cursor
I am not 100% sure though
z

Zach Klippenstein (he/him) [MOD]

10/27/2020, 10:45 PM
oh nice… although if it’s changing the size of the text after layout, would that not take effect until the next composition?
s

Siyamed

10/27/2020, 10:46 PM
I bet you know frames and recomposition better than me, but here is the story
If you measure your child first
If that child is text
Your variable that has a reference to the onTextLayout result will have the new value by the time you do your own layout
z

Zach Klippenstein (he/him) [MOD]

10/27/2020, 11:10 PM
This is what I thought the OP was trying to do, and this approach definitely has an off-by-one-frame issue (e.g. it doesn’t render correctly in the preview). You’d need to be able to measure the text before even composing the
Text
the first frame to do this correctly. You can do that with
FontMetrics
from the Android stdlib, but i don’t know if there’s a “pure” Compose way to do it.
s

Siyamed

10/27/2020, 11:11 PM
That one has yes
If you write your own layout block it doesnt
z

Zach Klippenstein (he/him) [MOD]

10/27/2020, 11:18 PM
How would you do that? The thing that’s changing here is the font size being passed to
Text
, and writing a custom layout wouldn’t affect that. Unless you mean write a custom text layout somehow? Or are you thinking of just scaling the text composable itself without changing the font size?
In other words, how would a custom layout change the size of the text?
s

Siyamed

10/27/2020, 11:26 PM
can I share something that does not compile?
🙂
I took your example and changed it into this:
Copy code
@Composable fun AutoText(text: String) {
  var size: TextUnit by remember { mutableStateOf(100.sp) }

  val textLayout: Ref<TextLayoutResult?> = remember { Ref() }
  
  val children = @Composable { 
    Text(
      text,
      fontSize = size,
      // Don't wrap since we're going to adjust the size to fit on one line.
      maxLines = 1,
	  softwrap = true,
      overflow = None,
      onTextLayout = { 
        textLayout.value = it
      }
    )
  }
  
  Layout(
      modifier = Modifier,
      children = children,
      measureBlock = { measurables, constraints ->
          val childConstraints = constraints.copy(maxHeight = Constraints.Infinity)
          val placeable = measurables.first().measure(childConstraints)		  
          val myHeight = constraints.constrainHeight(textLayout.value.height)
		  val myWidth = constraints.constrainWidth(textLayout.value.width)
          layout(myWidth, myHeight) {
              placeable.placeRelative(0, 0)
          }
      }
}
I added the textLayout val and also the measure block
I had something like that in mind
it is not complete (handling the min constraints etc (which we can use constraints.constrain).
z

Zach Klippenstein (he/him) [MOD]

10/27/2020, 11:29 PM
won’t that just cause the text to overflow/underflow the current layout node, e.g. get clipped if it’s too big and
clipToBounds
is used? Let me try it
s

Siyamed

10/27/2020, 11:30 PM
(unfortunately btw we removed overflow None for now and couldnt add it back yet
the text can get max width, which is basically its intrinsics
if your constraints are not constraining you to a width, it shouldn’t clip
z

Zach Klippenstein (he/him) [MOD]

10/27/2020, 11:37 PM
that doesn’t seem to work
s

Siyamed

10/27/2020, 11:38 PM
in my first version i wrote maxHeight, can you change it to maxWidth?
childConstraints = … maxWidth
z

Zach Klippenstein (he/him) [MOD]

10/27/2020, 11:39 PM
that fixes the horizontal clipping, but it’s still not resizing
This works!
scaling the layer feels like a giant hack though, and probably not memory efficient
s

Siyamed

10/27/2020, 11:52 PM
not only not memory efficient, it will not render correctly.
z

Zach Klippenstein (he/him) [MOD]

10/27/2020, 11:52 PM
yea
s

Siyamed

10/27/2020, 11:53 PM
thought seriously I coudnt run the sample, the idea is that you have the textlayout in your hand during layout
you can set the width and height of your own composable
I do not know how it looks on preview like that since I do not know the max constraints passed at that point
z

Zach Klippenstein (he/him) [MOD]

10/27/2020, 11:53 PM
Right, but that only changes how much room your parent gives you when it does its layout, it won’t change the size your children have measured and reported themselves to be. If you’re bigger than your children, there’ll just be empty space.
s

Siyamed

10/27/2020, 11:54 PM
I am confused 🙂
the idea was to have a TextField whose width is the width of the text is it correct?
you can set your width to be that width.
if your parent forces you to a width, there is nothing to do.
so in your example if they were in a row or scollable container it would work
z

Zach Klippenstein (he/him) [MOD]

10/27/2020, 11:55 PM
Wow, i’m way down the wrong rabbit hole. You’re right, the original question was about text field width, not text width
s

Siyamed

10/27/2020, 11:55 PM
🙂
z

Zach Klippenstein (he/him) [MOD]

10/27/2020, 11:55 PM
just ignore all my messages
one day i’ll actually learn to read
s

Siyamed

10/27/2020, 11:55 PM
oh no not ignore, I believe you went down to implement autosize text 🙂
z

Zach Klippenstein (he/him) [MOD]

10/27/2020, 11:55 PM
sorry for derailing this thread so massively
yep i did, which is completely irrelevant to the OP
s

Siyamed

10/27/2020, 11:56 PM
so it is possible to do without frame skip is the result ? 🙂
z

Zach Klippenstein (he/him) [MOD]

10/27/2020, 11:57 PM
what the OP asked, apparently 🙈
g

Grigorii Yurkov

10/29/2020, 1:31 PM
@Siyamed Returning to original question. Alpha-06 didn't solve the problem
s

Siyamed

10/30/2020, 4:29 AM
Can you share an image that shows the boundaries on alpha-06? At this point I will refer to
@Mihai Popa
he would know how to either match the Text to its parent or center the Text in the parent.
I used the capital T on purpose because the “text” and the Text are different. one being the rendered on screen other with the box around it.
m

Mihai Popa

10/30/2020, 12:06 PM
You can put the items in a
Row
and set
verticalAlignment
if all elements should be centered, or apply
Modifier.align()
on the elements that need centering
Does this solve the issue? Sorry if I'm misunderstanding the question it's been a long thread 🙂
g

Grigorii Yurkov

10/30/2020, 12:39 PM
Yes, it does. Thanks