Jetpack Compose shadow over LazyColumn - android

I'm trying to draw this shadow below list header, to give an illusion of LazyColumn items scrolling below (or behind) the header:
I tried:
using Modifier.shadow() but it does not yield desired result.
drawing a Box with gradient background, which does what I want, but get overdrawn with LazyColumn elements.
To counter this drawing over my gradient I tried the following:
putting Box after LazyColumn,
setting Modifier.zIndex(10f) to Box.
Of course, none of that worked. Immediately after LazyColumn elements were drawn, gradient disappeared.
What am I missing?

Have you tried a Surface with elevation?
From docs
https://developer.android.com/jetpack/compose/designsystems/material#elevation-overlays
Surface(
elevation = 2.dp,
color = MaterialTheme.colors.surface, // color will be adjusted for elevation
/*...*/
) {
// TODO - Put your list header here.
}

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.

MaterialCardView with top rounded corners should clip children

MaterialCardView clips its children when using rounded corners. If I use cardCornerRadius = true (which rounds all 4 corners of the card), the clipping behaves as expected -> children are not being drawn outside of the rounded area. If I try to round less corners (ie. only top corners, using ShapeAppearanceModel), then the clipping part is lost -> a top positioned child will be drawn over the rounded cornered area).
I realised that clip MaterialCardView calls
setClipToOutline(shapeAppearanceModel.isRoundRect(getBoundsAsRectF()));
inside of setShapeAppearanceModel, where isRoundRect returns true only if all four corners are rounded, so I tried applying clipToOutline = true on the MaterialCardView after setting the shapeAppearanceModel with top corners rounded, but with no similar result - children were still able to be drawn over the rounded part of the parent card.
What is actually triggering the clipping part and how can I force it on a top rounded shaped MaterialCardView?
LE: trial and error code:
// card is MaterialCardView
card.shapeAppearanceModel =
ShapeAppearanceModel()
.toBuilder()
.setTopRightCorner(CornerFamily.ROUNDED, cornerPx) // cornerPx = 24dp in pixels
.setTopLeftCorner(CornerFamily.ROUNDED, cornerPx)
.build()
card.apply {
preventCornerOverlap = true
clipChildren = true
clipToOutline = true
}
card.invalidateOutline()
Apply the following configurationsif you use shape appearance overlay in order to prevent the childs to overlapping from the corners:
Set cardPreventCornerOverlap to true
Then leave everything else that has to do with the corner settings as default (just delete the values from the textboxes in the design mode).
Then you should see something like this:

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

Prevent shadow clipping without adding content padding in Jetpack Compose

This question notes that in order to not clip the shadows on a LazyRow/LazyColumn in Jetpack Compose you need to add ContentPadding. However, I want to do the equivalent of "clipToPadding=false" without adding additional padding (the padding should be 0.dp). Is this possible? Or do you have to have some sort of 1.dp padding around the object?
Ex:
LazyRow(
state = listState,
flingBehavior = flingBehavior,
contentPadding = PaddingValues(all = 0.dp)
)
See clipping shadows on the lefthand edge:

Categories

Resources