Created
October 25, 2025 12:41
-
-
Save dev778g-me/39924eccfda33f61368914c49f8de20c to your computer and use it in GitHub Desktop.
created samsung nowbar concept
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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