Jetpack compose: elevate card from bottom - android

I was implementing Card shape in Jetpack Compose while I ran into this problem.
What I wanted was to only elevate one end or bottom of the card but I didn't find any relevant documents supporting that.
I tried looking into the implementation code of Card to get an idea (following is the code of the implementation):
#Composable
fun Surface(
modifier: Modifier = Modifier,
shape: Shape = RectangleShape,
color: Color = MaterialTheme.colors.surface,
contentColor: Color = contentColorFor(color),
border: BorderStroke? = null,
elevation: Dp = 0.dp,
content: #Composable () -> Unit
) {
Surface(
modifier = modifier,
shape = shape,
color = color,
contentColor = contentColor,
border = border,
elevation = elevation,
content = content,
clickAndSemanticsModifier = Modifier
.semantics(mergeDescendants = false) {}
.pointerInput(Unit) { }
)
}
but here it is accepting elevation in Dp, which means it with elevate the whole Card.
So I don't know how to implement it in Jetpack Compose, can someone help me with the implementation?
Edit:
I created an issue for this question: https://issuetracker.google.com/issues/227767373

You can elevate just the whole bottom like this
#Composable
fun BottomWithShadow(
content: #Composable ColumnScope.() -> Unit
) {
Box {
Card(
shape = RoundedCornerShape(
topEnd = 0.dp,
topStart = 0.dp,
bottomEnd = 0.dp,
bottomStart = 0.dp),
modifier = Modifier
.fillMaxWidth()
.height(50.dp)
.align(Alignment.BottomCenter),
elevation = 10.dp
) {}
Column(
modifier = Modifier
.clip(
RoundedCornerShape(
topEnd = 0.dp,
topStart = 0.dp,
bottomEnd = 0.dp,
bottomStart = 0.dp)
)
.background(color = Color.White),
content = content
)
}
}

Related

How to allow drag only on part of the SheetPeek of a BottomContent in BottomSheetScaffold?

The dragging part is possible on whole rectangle (Yellow in video) and I want it to be only allowed on the Grey icon
I can drag any part of the yellow part, whether up or down, I want to allow that behavior of dragging only on the Grey part
Left Video is the same as right video, except I made the right's sheetBackgroundColor transparent
#OptIn(ExperimentalMaterialApi::class)
#Composable
fun HomeScreen(modifier: Modifier = Modifier) {
BottomSheetScaffold(
topBar = { AppBar() },
sheetElevation = ZERO_DP,
sheetPeekHeight = BOTTOM_ICON_CONTAINER_SIZE,
sheetBackgroundColor = Color.Transparent,
sheetContent = {
BottomSheetContent(modifier)
}
) {
HomeContent()
}
#Composable
fun BottomSheetContent(
modifier: Modifier = Modifier,
) {
Column(
modifier = modifier
.fillMaxWidth()
.fillMaxHeight(0.8f)
) {
Box(
modifier = modifier
.padding(end = SPACING_QUADRUPLE)
.align(Alignment.End)
.clip(
RoundedCornerShape(
topStart = TRIPLE_CORNER_DP,
topEnd = TRIPLE_CORNER_DP
)
)
.size(BOTTOM_ICON_CONTAINER_SIZE)
.background(MaterialTheme.colors.secondary)
,
contentAlignment = Alignment.BottomCenter
)
{
Icon(
modifier = modifier,
painter = painterResource(id = R.drawable.ic_qr_code),
contentDescription = stringResource(
id = R.string.bottom_sheet_puller
),
tint = Color.Unspecified
)
}
Text(
modifier = modifier
.fillMaxWidth()
.background(MaterialTheme.colors.surface)
.padding(
start = SPACING_DOUBLE,
end = SPACING_DOUBLE,
bottom = SPACING_NORMAL
),
text = "Scan Serial With QR",
style = MaterialTheme.typography.h3,
)
Box(
modifier = modifier
.fillMaxSize()
.background(color = Color.DarkGray)
)
}
}
Wrong Behavior:
Correct Intended Behavior:
I tried replacing a rectangle composables with simple box, but bottom sheet was still considering the full width of the composable
There must be a better solution to intercept a drag gesture and leave all of it within the green box only, but this might suffice.
I made some changes to your BottomSheetContent, intercepting a drag gesture from a Row weighted transparent component and leaving it empty, you can try this one, and the drag gesture is only accepted by the green box,
#Composable
fun BottomSheetContent(
modifier: Modifier = Modifier,
) {
Column(
modifier = modifier
.fillMaxWidth()
.fillMaxHeight(0.8f)
) {
Row {
Box(
modifier = Modifier
.weight(1f)
.draggable(
orientation = Orientation.Vertical,
state = rememberDraggableState {
Toast.makeText(context, "Non Draggable Area", Toast.LENGTH_SHORT).show()
}
).fillMaxWidth().height(150.dp).background(Color.Transparent)) {
}
Box(
modifier = modifier
.padding(end = 8.dp)
.clip(
RoundedCornerShape(
topStart = 12.dp,
topEnd = 12.dp
)
)
.size(150.dp)
.background(MaterialTheme.colors.secondary),
contentAlignment = Alignment.BottomCenter
) {
Icon(
modifier = modifier,
imageVector = Icons.Default.Add,
contentDescription = "",
)
}
}
Text(
modifier = modifier
.fillMaxWidth()
.background(MaterialTheme.colors.surface)
.padding(
start = 8.dp,
end = 8.dp,
bottom = 4.dp
),
text = "Scan Serial With QR",
style = MaterialTheme.typography.h3,
)
Box(
modifier = modifier
.fillMaxSize()
.background(color = Color.DarkGray)
)
}
}
I can't show my pointer click here, but the toast shows when the left area outside of the green box is being dragged.

Blurring content layered behind a card using Jetpack Compose on Android

I am trying to achieve the blur effect like highlighted in this post:
I'm using Jetpack Compose:
#Composable
fun MainApp() {
val linearGradientBrush = Brush.linearGradient(
colors = listOf(
Color(0xFF5995EE),
Color(0xFFB226E1),
Color(0xFFE28548)
),
start = Offset(Float.POSITIVE_INFINITY, 0f),
end = Offset(0f, Float.POSITIVE_INFINITY),
)
val transparentGradientBrush = Brush.linearGradient(
colors = listOf(
Color(0x66FFFFFF),
Color(0x1AFFFFFF)
)
)
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Box() {
Card(
modifier = Modifier
.size(150.dp)
// .blur(10.dp, edgeTreatment = BlurredEdgeTreatment.Unbounded)
.clip(shape = CircleShape)
.background(linearGradientBrush),
backgroundColor = Color.Transparent,
elevation = 0.dp,
) {
}
Card(
modifier = Modifier
.size(150.dp)
.offset(x = -75.dp, y = 40.dp)
.blur(5.dp, edgeTreatment = BlurredEdgeTreatment.Unbounded)
.clip(RoundedCornerShape(30.dp))
.background(transparentGradientBrush),
backgroundColor = Color.Transparent,
elevation = 0.dp
) {
}
}
}
}
However, the output I get is this:
How do I achieve the effect from the tweet above the layer in front also blurs the layer behind? Is there a way to achieve this?
https://github.com/x3rocode/xblur-compose/tree/main
I made simple realtime compose blur!
try this.

No ripple effect in Jetpack Compose

There is no ripple effect when I click on MyBox() I've added MyTheme(){} to main #Composable screen but it doesn't work. Is something missing?
#Composable
private MyBox(onClickInvoked: () -> Unit) {
MyAppTheme(isSystemInDarkTheme()) {
Box(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.clip(RoundedCornerShape(10.dp))
.background(MaterialTheme.colors.onBackground)
.clickable(onClick = { onClickInvoked.invoke() })
.padding(horizontal = 10.dp, vertical = 15.dp)
) {
Text(
text = "My text",
modifier = Modifier
.align(Alignment.CenterStart)
.padding(end = 95.dp)
.wrapContentWidth()
.wrapContentHeight(),
color = MaterialTheme.colors.primary
)
Image(
painter = painterResource(R.drawable.icon),
modifier = Modifier
.align(Alignment.CenterEnd)
.padding(end = 20.dp)
.size(60.dp)
)
}
}
}
With compose 1.0.5, I see the default indication after set clickable is
LocalIndication.current. And LocalIndication.current is PlatformRipple. Therefore, after you set clickable to your Box, it will have ripple effect.
In your case, I think the ripple effect won't display because your Box background is too dark (normally MaterialTheme.colors.onBackground is black on Light theme)
I think you can change the ripple effect color to make it easy to see.
Surface(
onClick = { onClickInvoked.invoke() },
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(10.dp),
color = MaterialTheme.colors.onBackground, // normally it is black on Light theme
indication = rememberRipple(color = Color.White) // color for your ripple, you can use other suitable MaterialTheme.colors for your case to support Light/Dark mode
) {
Box(modifier = Modifier.padding(horizontal = 10.dp, vertical = 15.dp)) {
// your Box content
...
}
}
There is a Modifier.indication but after testing I see it not working with Modifier.clickable so I use Surface
I don't really know if there is a problem with your theme. I try to pass the material theme, and the ripples will display normally
MaterialTheme() {
Box(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.clip(RoundedCornerShape(10.dp))
.background(MaterialTheme.colors.secondary)
.clickable(onClick = { t = "My text" })
.padding(horizontal = 10.dp, vertical = 15.dp)
) {
Text(
text = t,
modifier = Modifier
.align(Alignment.CenterStart)
.padding(end = 95.dp)
.wrapContentWidth()
.wrapContentHeight(),
color = MaterialTheme.colors.primary
)
Image(
painter = painterResource(R.drawable.ic_launcher_foreground),
modifier = Modifier
.align(Alignment.CenterEnd)
.padding(end = 20.dp)
.size(60.dp),
contentDescription = ""
)
}
}

How to remove border of card view with jetpack compose

I am facing the issue of border remove from card view in jetpack compose.
Kindly guide me on how to do achieve border removal from card view functionality.
My code is below but not working correctly.
Code
Card(
shape = RoundedCornerShape(0.dp),
border = BorderStroke(0.dp, Transparent),
modifier = Modifier
.height(100.dp)
.padding(start = 10.dp, top = 40.dp, end = 10.dp)
.border(0.dp, Transparent),
) {
Column(
modifier = Modifier
.fillMaxWidth()
.clickable {
submit()
},
) {
Text(
modifier = Modifier
.weight(1f)
.padding(start = 20.dp, top = 20.dp, bottom = 20.dp)
.wrapContentWidth(Alignment.Start),
text = "Submit",
style = typography.h4,
)
}
}
Actually, By default, there is no border in Card. What you are seeing is 1.dp elevation. So if you don't want any elevation make it 0.dp like the following.
Card(
modifier = Modifier
.height(100.dp)
.padding(start = 10.dp, top = 40.dp, end = 10.dp),
elevation = 0.dp
) {
Your content..
}

Why jetpack compose elevation clip my shadow?

I have a problem with jetpack compose elevation render. I'm trying to add elevation on Surface but my UI seems to with clipped shadow. Also, how can I add a colorful shadow on my Surface?
See the below on the screenshot
#Composable
fun DiscoverItem() {
Surface(
contentColor = Color(0xFFFFFFFF),
modifier = Modifier.preferredWidthIn(min = 145.dp).preferredHeight(56.dp),
shape = CircleShape,
elevation = 8.dp,
) {
Row(
modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Surface(
modifier = Modifier.preferredSize(40.dp),
shape = CircleShape,
color = Color(0xFFFFC3D8)
) {
Image(
imageResource(R.drawable.pin_icon),
modifier = Modifier.size(width = 18.dp, height = 24.dp),
contentScale = ContentScale.Fit
)
}
Spacer(modifier = Modifier.padding(start = 10.dp))
Text(
"YOUR AREA",
style = MaterialTheme.typography.body2,
color = Color(0xFFFC1055)
)
}
}
}
#Composable
#Preview
fun DiscoverItemPreview() {
DiscoverItem()
}
You don't have enough content on bottom of your layout. You can add spacer to view your shadow.
#Composable
#Preview
fun DiscoverItemPreview() {
Column{
DiscoverItem()
Spacer(modifier = Modifier.height(20.dp))
}
}
And about colorful shadow, compose min sdk is Android Lollpop and skia version for lollipop doesnot supports colorful shadow/elevation. Leland Richardson had talked about this issue in his youtube video on Compose dogfooding. here
I use surface to wrap the shadowed card and it gives me expected result.
Surface(
elevation = 4.dp,
color = MaterialTheme.colors.surface,
shape = Shapes.medium,
) {
Card(
modifier = Modifier
.fillMaxWidth()
.animateContentSize(
animationSpec = tween(
durationMillis = 300,
easing = LinearOutSlowInEasing
)
),
elevation = 8.dp,
shape = Shapes.medium,
onClick = {
isExpanded = !isExpanded
}
) {}}
enter image description here

Categories

Resources