How to provide relative sizes in Jetpack Compose - android

I have a Box layout and I want to layout child views relative to the size of the parent box. This is achievable in SwiftUI using Geometry Reader. How can I achieve something similar in Jetpack Compose ?

You can use BoxWithConstraints instead of a Box.
You can work with the measurement constraints available in the scope of the content lambda.
Something like:
BoxWithConstraints {
Box(Modifier.width(maxWidth*0.7f).height(30.dp).background(Color.Blue))
Box(Modifier.width(maxWidth*0.3f).height(30.dp).background(Color.Yellow))
}
Otherwise you can use the Box and fillMaxWidth and fillMaxHeight modifiers with a fraction.
Box(){
Box(Modifier.fillMaxWidth(0.7f).height(30.dp).background(Color.Blue))
Box(Modifier.fillMaxWidth(0.3f).height(30.dp).background(Color.Yellow))
}

Related

Is there a way to use wrapContentHeight() with Canvas in Android Compose UI?

I need to make a Canvas wrap the content of its children as shown in the image. the label is shown based on a flag (meaning: it is not always visible). and I have another label (not shown in the picture) at the top (That indicates the value in the bar).
What I don't want to have is fixed height Canvas(modifier = modifier.fillMaxWidth().height(50.dp)) but instead Canvas(modifier = modifier.fillMaxWidth().wrapContentHeight())
Note that the height of the bar is fixed. the marker can be fixed as well. but showing/hiding the text need to make the canvas' height updated. I don't want to have a fixed value.
Any ideas?
I tried to use a boolean to give the canvas a different height. but I'am looking for something more elegant
.height(
if (showLabels) {
50.dp
} else {
30.dp
}
)

android, how to set a same height for my cards without hardcode in lazy row

I have a lazy row with items that have wrap content height.
my problem is that some texts of these items is visible or invisible base of that item. so the height of that cart is not fix and it will change.
how can I find the max height of that item (with all texts) and set that height to all items.
I do not want to set a hard code height to my items (like 300.dp)
as you can see in this image: the below button change its position based on the card's height.
I want that button fix in its place and not move up and down.
https://i.stack.imgur.com/R0Tc6.png
how can I fix that problem?
Have you tried experimenting around onGloballyPositioned{..} modifier property?
val localDensity = LocalDensity.current
Text(modifier = Modifier
.onGloballyPositioned { thisText ->
with (localDensity) {
thisText.size.height.toDp()
}
},
text = "Text"
)
Edit: Intrinsic Measurement is not allowed in LazyList components, have a look at this post, looks like similar to yours.
Jetpack Compose: Row with all items same height
Also, Constraintlayout maybe a good thing to experiment on.
One of the rules of Compose is that you should only measure your children once; measuring children twice throws a runtime exception. However, there are times when you need some information about your children before measuring them.
If you have a look at the Android documentation for Intrinsic Measurements, you will have a clear idea of what to do. In your scenario, you need to force Compose to measure the size of your children to adjust the parent composable's dimensions accordingly.
This medium article gives an easier example on how to use IntrinsicSize in Compose.

Custom layout ignores size of composeable

I'm currently playing around with custom Layouts in Jetpack Compose. This is what i got so far just for testing:
#Preview(widthDp = 1000, heightDp = 1000)
#Composable
fun MyLayout() {
Layout({ Box(Modifier.size(48.dp).background(Color.Blue)) }) { measurables, constraints ->
val placeables = measurables.map { it.measure(constraints) }
layout(constraints.maxWidth, constraints.maxHeight) {
placeables.forEach { it.place(0, 0) }
}
}
}
My problem here is that the Box fills the whole layout and not only it's size of 48.dp. Can someone explain to me why this is? I read here about creating custom layouts but couldn't find anything usefull.
Layout size is determined by the size passed into layout(width, height).
Your Layout doesn't have any modifiers, that's why it has maxWidth/maxHeight constraints equal to available spacing. Using layout(constraints.maxWidth, constraints.maxHeight) has the same effect as applying Modifier.fillMaxSize. Actually with Modifier.fillMaxSize your'll set both max and min constraints to the available size.
To solve this you have two options:
Apply Modifier.size to the Layout itself, instead of applying to the Box - in this case max/min constraints will be 48.dp
Calculate layout size depending on placeable. The actual code depend on what layout do you expect to get. Your code looks like Box analog, so you need maximum of all placeable sizes:
layout(placeables.maxOfOrNull { it.width } ?: 0, placeables.maxOfOrNull { it.height } ?: 0) {
The reason why the blue box fills the entire Layout is because of a combination of a few things: (1) you specify dimensions for the #Preview annotation, (2) you use the Layout's constraints unmodified to measure the box, and (3) the use of the size modifier.
Because of point 1, the constraints of the Layout will have both the minimum and maximum set to what was specified in the Preview dimensions. Because of point 2 those strict minimums and maximums are used to measure the box. And because of point 3 the incoming constraints take priority over the requested size (that's the way the size modifier works).
Mitigating each of those points will solve your problem.
As you already found out from one of the other answers, removing the width and height from the preview annotation will make those seem right. That is because without the width and height specified in the Preview annotation, the constraints will have a minimum of 0, so the child measurable are now allowed to take the size they want.
The recommended way though is to fix point 2: change the constraints to fit the requirements of your custom layout before you pass them to the measurables' measure methods. In this case, you probably want to create a copy of the constraints and set the minimum width and height to 0.
And finally you can fix point 3 by using requiredSize instead, which will size the measurable to the required size regardless, even though it will still communicate to its parents a size that's within the constraints. This is usually not recommended in production code because it makes sizing absolute, but for a preview it should be fine, and for tests it could even be desirable.

Does Jetpack Compose have the tools to create custom OverscrollEffect?

Is there a way to create OverscrollEffect in jetpack compose?
Something like this:
The overscroll effect can be controlled by the LocalOverscrollConfiguration, which currently has the following parameters:
glowColor - color for the glow effect, if the platform effect is a glow effect, otherwise ignored.
forceShowAlways - force show overscroll even if content doesn't scroll (is smaller than a scrollable container itself)
drawPadding - the amount of padding to apply from scrollable container bounds to effect before drawing it
CompositionLocalProvider(
LocalOverscrollConfiguration provides OverScrollConfiguration(
glowColor = Color.Gray,
forceShowAlways = false,
drawPadding = PaddingValues()
)
) {
// effected views
}
If you think there should be more parameters, you can let the maintainers know by creating a feature request.
p.s. in 1.2.0-rc01 LocalOverScrollConfiguration has being renamed to LocalOverscrollConfiguration

How to do match_parent in iOS

I am used to having an Android background where I do:
android_layout_width="match_parent" or android_layout_height="match_parent"
How is this behavior done on iOS, using xib?
1) Set frame of child view matching parent's view bounds.
2) Enable autoresizing mask like in screenshot.
You have to create two constraints from the child to it's parent view:
equal width
equal height
It's also possible to define a margin (select the created constraint within the size inspector)

Categories

Resources