how to set gravity in jetpack compose Text - android-jetpack-compose

I have a text component that height is 48dp and want to set the text center in vertical.
Like the TextView with 48dp height and gravity is center_vertical.
Or I have to put it(Text compose) in Surface component?

Yes, that is correct, you would need to put it in a box for instance, or a column, and center it that way.
Box(modifier = Modifier.fillMaxSize, contentAlignment = Alignment.Center){
Text(text = "My Text") }

Related

How do I vertically center an icon with a multiline text label's first line of text?

Problem
We want an icon that is centered vertically with the first line of text of an adjacent view, and we want it to be aligned regardless of text length, icon size or font size. In other words, we want the following result:
The desired result is above: the red icon is aligned with the center of the first line of textIn SwiftUI, the default vertical alignment options are:
.top
.center
.bottom
.firstTextBaseline
.lastTextBaseline
.center is what we want for a single line of text, but if we use it for multiline text we get:
And if we use .firstTextBaseline, we are close but it doesn't quite center the image (this is more obvious as the text size changes):
Solution
We need to use a combination of alignment guides and arithmetic. The solution in code is below:
struct ContentView: View {
var body: some View {
HStack(alignment: .firstTextBaseline) {
Rectangle()
.fill(.red)
.frame(width: 16, height: 16)
.alignmentGuide(.firstTextBaseline) { context in
context[VerticalAlignment.center]
}
Text(greeting)
.font(.title3)
.background(.blue)
.alignmentGuide(.firstTextBaseline) { context in
let remainingLine = (context.height - context[.lastTextBaseline])
let lineHeight = context[.firstTextBaseline] + remainingLine
let lineCenter = lineHeight / 2
return lineCenter
}
}
}
}
In the above example, the rectangle center is aligned with the center of the first line:
How it works
The Rectangle is a stand-in for an icon.
The .firstTextBaseline of alignmentGuide is actually only used as a key to match the against the HStack alignment. So it doesn't make a difference except that the HStack, Rectangle and Text all are using the same vertical alignment scheme.
The context[VerticalAlignment.center] of the Rectangle is returned to indicate that the center of the Rectangle will be be aligned with the other alignment guides of its view siblings (thus centering the Rectangle)
We need to do additional math for the Text to find where the center of the first line of text lies. The arithmetic uses the lastTextBaseline and the height of the entire Text to calculate the region below the text baseline. By adding this to the firstTextBaseline and dividing by 2, we determine where the center of the first line of text lies. The result of this calculation is returned as the alignment guide, for alignment with its siblings (in this case, the center of the Rectangle that we returned already)

Jetpack Compose - Scrollable Column and clip to padding

I have a simple screen with scrollable vertical column. It contains some text and images.
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
.verticalScroll(rememberScrollState()),
) {
...
}
The content is scrollable but it clips to defined padding. Meaning when you scroll, you can see that overscroll shadow does not fill the entire screen, but it is bound to the padding. It looks really bad:
In XML world you would use android:clipToPadding="false" to "fill" the container. Is there equivalent of that in Compose?
Got it, apparently order of modifier constraints matters, didn't know that.
Just place padding as last one.
Column(
modifier = Modifier
.fillMaxWidth()
.verticalScroll(rememberScrollState())
.padding(16.dp),
) {
...
}

How to trim image edge in Jetpack Compose?

Let's say I want to show a composable view with an image. Instead of an original image I would like to trim part of the image away, for example 20% from the right edge. How would I do this? Can I use a .clip-modifier with a custom shape?
You can create your own shape and clip using that shape as
private val cropShape = GenericShape { size: Size, layoutDirection: LayoutDirection ->
addRect(Rect(0f, 0f, size.width * .8f, size.height))
}
0.8 is arbitrary number, you can customize your Rectangle as you wish
Image(
modifier = Modifier.clip(cropShape),
painter = bitmap,
contentDescription = null
)
The one on top without clip modifier, the one at the bottom is clipped with Modifier.clip(cropShape)
You can crop it with a shape, as #Thracian suggests, but in that case the view size won't change. For example, if you put it in Row, you will have an unexpected padding to next item.
Instead, you can use Modifier.layout to actually reduce the size of the view, and clip it with RectangleShape, since by default Compose views are not clip to bounds.
Image(
painter = painterResource(id = R.drawable.my_image_1),
contentDescription = null,
modifier = Modifier
.clip(RectangleShape)
.layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
layout(width = placeable.width * 8 / 10, height = placeable.height) {
placeable.place(0, 0)
}
}
)

Jetpack Compose - Row Clipping Children When Width Increases

Here on the right , I have a list of items in a composable , Every item is inside a row , All the items are inside a column
All the children of the are getting clipped to fit the screen which I don't want , I want these items to render completely even if outside of screen since I have a zoomable container above them
As you can see how text in the text field is all in one line vertically rather than expanding the width , This is the problem
Code :
Row(
modifier = modifier.zIndex(3f),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
) {
SimpleNodesList(
modifier = Modifier.padding(8.dp),
parentNode = state.center,
nodes = state.center.left,
renderRight = false,
)
SimpleNode(node = state.center, parentNode = null)
SimpleNodesList(
modifier = Modifier.padding(8.dp),
parentNode = state.center,
nodes = state.center.right,
renderLeft = false
)
}
Simple Nodes List is a column of rows , I have one column on left and one on the right , If the width of the left column increases , right row get's clipped by the screen
Using this modifier does the job for the row , In my case I also needed this layout modifier , wrapContentSize(unbounded = true) was working but children weren't clickable for some reason outside the bounds of the zoom container !
I also had to create a modifier zoomable rather than use a zoomable box , so the zoomable touch events would be dispatched on the this composable rather than the parent !
modifier = Modifier
.layout { measurable, constraints ->
val r =
measurable.measure(constraints = constraints.copy(maxWidth = Constraints.Infinity))
layout(r.measuredWidth, r.measuredHeight, placementBlock = {
r.placeWithLayer(0, 0, 0f) {
}
})
}
.wrapContentSize(unbounded = true)
If you are using hard-coded width for the text, applying Modifier.wrapContentSize() on every container might do the job
Use SimpleFlowRow in place of Row. It will fix the clipping issue.

How do I center an annotation title?

So I have a map with annotations that represent bikes. All of them have a title, an image, and a button. The title is on the left side by default as far as I can say. Is there any way I can center the title?
You can set the textAlignment to center
yourTitle.textAlignment = .center

Resources