Skip to content

Instantly share code, notes, and snippets.

@dev778g-me
Created October 25, 2025 12:41
Show Gist options
  • Select an option

  • Save dev778g-me/39924eccfda33f61368914c49f8de20c to your computer and use it in GitHub Desktop.

Select an option

Save dev778g-me/39924eccfda33f61368914c49f8de20c to your computer and use it in GitHub Desktop.
created samsung nowbar concept
package com.example.nowbar
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.spring
import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.animation.shrinkVertically
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Call
import androidx.compose.material.icons.rounded.CallEnd
import androidx.compose.material.icons.rounded.DoDisturbOn
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.composables.icons.lucide.Camera
import com.composables.icons.lucide.Lucide
import com.composables.icons.lucide.MessageSquare
import com.kyant.backdrop.backdrops.LayerBackdrop
import com.kyant.backdrop.backdrops.layerBackdrop
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
import com.kyant.backdrop.drawBackdrop
import com.kyant.backdrop.effects.blur
import com.kyant.backdrop.effects.lens
@Composable
fun LockScreen(modifier: Modifier = Modifier) {
//backdrop library
val layerBackdrop = rememberLayerBackdrop()
// state to hold the clicked state of the nowbar
var clicked by remember { mutableStateOf(false) }
// to animate the scale
val scale by animateFloatAsState(
targetValue = if (clicked) 1.5f else 1f,
// spring animations for the bouncy effect
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessMediumLow
)
)
// animating the change in padding when scaling the box
val verticalPadding by animateDpAsState(
targetValue = if (clicked) 48.dp else 24.dp
)
Box(
modifier = modifier.fillMaxSize()
) {
// wallpaper
Image(
modifier = modifier.layerBackdrop(
backdrop = layerBackdrop
),
painter = painterResource(
id = R.drawable.yel
),
contentDescription = null,
contentScale = ContentScale.FillHeight
)
Column(
modifier = modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
//pushing the composable to the below by giving weight of 1f
modifier = modifier.weight(1f)
) {
}
Row(
verticalAlignment = Alignment.CenterVertically
) {
// camera shortcut
AnimatedVisibility (
visible = !clicked,
enter = scaleIn(
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessMediumLow
)
),
exit = slideOutHorizontally() + scaleOut(
animationSpec = spring(
dampingRatio = Spring.DampingRatioLowBouncy,
stiffness = Spring.StiffnessMediumLow
)
)
) {
LiquidIconButton(
backdrop = layerBackdrop,
imageVector = Lucide.Camera
)
}
// the now bar
Box(
modifier = modifier
.scale(
scaleX = scale,
scaleY = scale
)
.padding(
horizontal = 16.dp,
vertical = verticalPadding
)
.drawBackdrop(
onDrawSurface = {
drawRect(
brush = Brush.linearGradient(
colors = listOf(
Color.Green.copy(
alpha = 0.5f
), Color.Transparent, Color.Transparent
)
)
)
},
backdrop = layerBackdrop,
shape = { RoundedCornerShape(34.dp) },
effects = {
blur(160f.dp.toPx())
lens(
refractionHeight = 24f.dp.toPx(),
refractionAmount = 48f.dp.toPx(),
depthEffect = true
)
}
)
.clickable(
onClick = {
clicked = !clicked
}
),
contentAlignment = Alignment.Center
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = modifier.padding(
vertical = 8.dp,
horizontal = 12.dp
)
) {
Box(
modifier = modifier.clip(
CircleShape
)
){
Image(
modifier = modifier.size(38.dp),
painter = painterResource(
id = R.drawable.pfp
),
contentDescription = null
)
}
Column(
modifier = modifier
.padding(
horizontal = 8.dp
)
// animating the content size change and giving it spring animation
.animateContentSize(
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessMediumLow
)
)
) {
Text(
text = "Debanshhh",
color = Color.White,
style = MaterialTheme.typography.labelMedium,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
fontWeight = FontWeight.ExtraBold
)
Row {
AnimatedContent(
targetState = clicked
) {
if (it){
Text(
text = "Mobile ",
style = MaterialTheme.typography.labelSmall,
color = Color.White,
fontWeight = FontWeight.Light
)
}
}
Text(
text = "6967152841",
style = MaterialTheme.typography.labelSmall,
color = Color.White,
fontWeight = FontWeight.Light
)
}
// i can improve it i guess
// row buttons {expanded state}
AnimatedVisibility(
visible = clicked,
enter = fadeIn(
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessMediumLow
)
) + expandVertically(
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessMediumLow
)
),
exit = fadeOut(
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessMediumLow
)
) + shrinkVertically(
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessMediumLow
)
)
) {
Row(
modifier = modifier.padding(top = 8.dp)
) {
PillLiquidIconButton(
backdrop = layerBackdrop,
icon = Icons.Rounded.Call,
color = Color.Green.copy(alpha = 0.5f)
)
Spacer(modifier = modifier.width(4.dp))
PillLiquidIconButton(
backdrop = layerBackdrop,
icon = Icons.Rounded.CallEnd,
color = Color.Red.copy(alpha = 0.9f)
)
}
}
}
// row buttons {idle state } i can improve it ig yes
AnimatedContent(
targetState = clicked,
transitionSpec = {
fadeIn(
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessMediumLow
)
) togetherWith fadeOut(
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessMediumLow
)
)
}
) { isClicked ->
if (!isClicked) {
// Two buttons when collapsed
Row {
PillLiquidIconButton(
backdrop = layerBackdrop,
icon = Icons.Rounded.Call,
color = Color.Green.copy(alpha = 0.5f)
)
Spacer(modifier = modifier.width(4.dp))
PillLiquidIconButton(
backdrop = layerBackdrop,
icon = Icons.Rounded.CallEnd,
color = Color.Red.copy(alpha = 0.9f)
)
}
} else {
// Single button when expanded - maintains same width
Box(
contentAlignment = Alignment.Center
) {
// Invisible placeholder to maintain width
Row(modifier = modifier.alpha(0f)) {
PillLiquidIconButton(
backdrop = layerBackdrop,
icon = Icons.Rounded.Call,
color = Color.Green.copy(alpha = 0.5f)
)
Spacer(modifier = modifier.width(4.dp))
// PillLiquidIconButton(
// backdrop = layerBackdrop,
// icon = Icons.Rounded.CallEnd,
// color = Color.Red.copy(alpha = 0.9f)
// )
}
// Visible centered button
LiquidIconButton(
modifier = modifier.scale(0.7f),
backdrop = layerBackdrop,
imageVector = Lucide.MessageSquare
)
}
}
}
//
}
}
// the dnd shortcut
AnimatedVisibility(
visible = !clicked,
enter = scaleIn(
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessMediumLow
)
),
exit = slideOutHorizontally() + scaleOut(
animationSpec = spring(
dampingRatio = Spring.DampingRatioLowBouncy,
stiffness = Spring.StiffnessMediumLow
)
)
) {
LiquidIconButton(
backdrop = layerBackdrop,
imageVector = Icons.Rounded.DoDisturbOn
)
}
}
}
}
}
@Composable
fun LiquidIconButton(modifier: Modifier = Modifier, backdrop: LayerBackdrop, imageVector: ImageVector) {
Box(
modifier = modifier.drawBackdrop(
onDrawSurface = {
drawRect(
color = Color.White.copy(alpha = 0.5f)
)
},
backdrop = backdrop,
effects = {
},
shape = { CircleShape}
)
){
Icon(
modifier = modifier.padding(10.dp),
imageVector = imageVector,
contentDescription = null
)
}
}
@Composable
fun PillLiquidIconButton(
modifier: Modifier = Modifier,
backdrop: LayerBackdrop,
icon: ImageVector,
color: Color
) {
Box(
modifier = modifier.drawBackdrop(
onDrawSurface = {
drawRect(
color =color
)
},
backdrop = backdrop,
effects = {
},
shape = { RoundedCornerShape(16.dp)}
)
){
Icon(
tint = Color.White,
modifier = modifier
.padding(
horizontal = 12.dp,
vertical = 6.dp
)
.size(ButtonDefaults.IconSize),
imageVector = icon,
contentDescription = null
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment