diff --git a/README.md b/README.md
index 57bf671..72bddd7 100644
--- a/README.md
+++ b/README.md
@@ -4,29 +4,27 @@
Apple's Liquid Glass effect for Android Jetpack Compose.
-⚠️ The library is in alpha stage, every API may be changed, use it on your own risk.
-
## Docs
[](https://jitpack.io/#Kyant0/AndroidLiquidGlass)
+⚠️ The library is in alpha stage, every API may be changed, use it on your own risk.
+
[Latest docs](https://kyant.gitbook.io/backdrop)
[legacy docs (before 1.0.0-alpha10)](docs/LegacyDocs.md)
## Demos
+- [Catalog](./catalog/release/catalog-release.apk)
+
+
+
- [Playground app](./app/release/app-release.apk), Android 13 and above is required.

-- [Catalog](./catalog/release/catalog-release.apk)
-
-| | |
-|:---------------------------------------------------------------------------------:|:---------------------------------------------------------------------------:|
-|
|
|
-
-## Comparing with iOS
+## Comparing effects with iOS
iOS device: iPhone 16 Pro Max (emulator), using [GlassExplorer](https://github.com/ktiays/GlassExplorer)
diff --git a/artworks/catalog.jpg b/artworks/catalog.jpg
new file mode 100644
index 0000000..a094c78
Binary files /dev/null and b/artworks/catalog.jpg differ
diff --git a/artworks/catalog_bottom_tabs.jpg b/artworks/catalog_bottom_tabs.jpg
deleted file mode 100644
index dcb1eb9..0000000
Binary files a/artworks/catalog_bottom_tabs.jpg and /dev/null differ
diff --git a/artworks/catalog_control_center.jpg b/artworks/catalog_control_center.jpg
deleted file mode 100644
index 9bdb41f..0000000
Binary files a/artworks/catalog_control_center.jpg and /dev/null differ
diff --git a/backdrop/src/main/java/com/kyant/backdrop/ContentBackdropModifier.kt b/backdrop/src/main/java/com/kyant/backdrop/ContentBackdropModifier.kt
index 75aa265..2688a34 100644
--- a/backdrop/src/main/java/com/kyant/backdrop/ContentBackdropModifier.kt
+++ b/backdrop/src/main/java/com/kyant/backdrop/ContentBackdropModifier.kt
@@ -30,19 +30,19 @@ import com.kyant.backdrop.shadow.Shadow
import com.kyant.backdrop.shadow.ShadowElement
fun Modifier.contentBackdrop(
- shapeProvider: () -> Shape,
+ shape: () -> Shape,
highlight: (() -> Highlight?)? = DefaultHighlight,
shadow: (() -> Shadow?)? = DefaultShadow,
- layerBlock: (GraphicsLayerScope.() -> Unit)? = null,
+ layer: (GraphicsLayerScope.() -> Unit)? = null,
onDrawBehind: (DrawScope.() -> Unit)? = null,
onDrawSurface: (DrawScope.() -> Unit)? = null,
effects: BackdropEffectScope.() -> Unit
): Modifier {
- val shapeProvider = CachedBackdropShapeProvider(shapeProvider)
+ val shapeProvider = CachedBackdropShapeProvider(shape)
return this
.then(
- if (layerBlock != null) {
- Modifier.graphicsLayer(layerBlock)
+ if (layer != null) {
+ Modifier.graphicsLayer(layer)
} else {
Modifier
}
@@ -70,7 +70,7 @@ fun Modifier.contentBackdrop(
.then(
ContentBackdropElement(
shapeProvider = shapeProvider,
- layerBlock = layerBlock,
+ layerBlock = layer,
onDrawBehind = onDrawBehind,
onDrawSurface = onDrawSurface,
effects = effects
diff --git a/backdrop/src/main/java/com/kyant/backdrop/DrawBackdropModifier.kt b/backdrop/src/main/java/com/kyant/backdrop/DrawBackdropModifier.kt
index 6e73d35..665a6a6 100644
--- a/backdrop/src/main/java/com/kyant/backdrop/DrawBackdropModifier.kt
+++ b/backdrop/src/main/java/com/kyant/backdrop/DrawBackdropModifier.kt
@@ -41,20 +41,21 @@ private val DefaultOnDrawBackdrop: DrawScope.(DrawScope.() -> Unit) -> Unit = {
fun Modifier.drawBackdrop(
backdrop: Backdrop,
- shapeProvider: () -> Shape,
+ shape: () -> Shape,
highlight: (() -> Highlight?)? = DefaultHighlight,
shadow: (() -> Shadow?)? = DefaultShadow,
- layerBlock: (GraphicsLayerScope.() -> Unit)? = null,
+ layer: (GraphicsLayerScope.() -> Unit)? = null,
onDrawBehind: (DrawScope.() -> Unit)? = null,
onDrawBackdrop: DrawScope.(drawBackdrop: DrawScope.() -> Unit) -> Unit = DefaultOnDrawBackdrop,
onDrawSurface: (DrawScope.() -> Unit)? = null,
+ onDrawFront: (DrawScope.() -> Unit)? = null,
effects: BackdropEffectScope.() -> Unit
): Modifier {
- val shapeProvider = CachedBackdropShapeProvider(shapeProvider)
+ val shapeProvider = CachedBackdropShapeProvider(shape)
return this
.then(
- if (layerBlock != null) {
- Modifier.graphicsLayer(layerBlock)
+ if (layer != null) {
+ Modifier.graphicsLayer(layer)
} else {
Modifier
}
@@ -83,10 +84,11 @@ fun Modifier.drawBackdrop(
DrawBackdropElement(
backdrop = backdrop,
shapeProvider = shapeProvider,
- layerBlock = layerBlock,
+ layerBlock = layer,
onDrawBehind = onDrawBehind,
onDrawBackdrop = onDrawBackdrop,
onDrawSurface = onDrawSurface,
+ onDrawFront = onDrawFront,
effects = effects
)
)
@@ -99,6 +101,7 @@ private class DrawBackdropElement(
val onDrawBehind: (DrawScope.() -> Unit)?,
val onDrawBackdrop: DrawScope.(drawBackdrop: DrawScope.() -> Unit) -> Unit,
val onDrawSurface: (DrawScope.() -> Unit)?,
+ val onDrawFront: (DrawScope.() -> Unit)?,
val effects: BackdropEffectScope.() -> Unit
) : ModifierNodeElement() {
@@ -110,6 +113,7 @@ private class DrawBackdropElement(
onDrawBehind = onDrawBehind,
onDrawBackdrop = onDrawBackdrop,
onDrawSurface = onDrawSurface,
+ onDrawFront = onDrawFront,
effects = effects
)
}
@@ -121,6 +125,7 @@ private class DrawBackdropElement(
node.onDrawBehind = onDrawBehind
node.onDrawBackdrop = onDrawBackdrop
node.onDrawSurface = onDrawSurface
+ node.onDrawFront = onDrawFront
node.effects = effects
node.invalidateDrawCache()
}
@@ -133,6 +138,7 @@ private class DrawBackdropElement(
properties["onDrawBehind"] = onDrawBehind
properties["onDrawBackdrop"] = onDrawBackdrop
properties["onDrawSurface"] = onDrawSurface
+ properties["onDrawFront"] = onDrawFront
properties["effects"] = effects
}
@@ -146,6 +152,7 @@ private class DrawBackdropElement(
if (onDrawBehind != other.onDrawBehind) return false
if (onDrawBackdrop != other.onDrawBackdrop) return false
if (onDrawSurface != other.onDrawSurface) return false
+ if (onDrawFront != other.onDrawFront) return false
if (effects != other.effects) return false
return true
@@ -158,6 +165,7 @@ private class DrawBackdropElement(
result = 31 * result + (onDrawBehind?.hashCode() ?: 0)
result = 31 * result + onDrawBackdrop.hashCode()
result = 31 * result + (onDrawSurface?.hashCode() ?: 0)
+ result = 31 * result + (onDrawFront?.hashCode() ?: 0)
result = 31 * result + effects.hashCode()
return result
}
@@ -170,6 +178,7 @@ private class DrawBackdropNode(
var onDrawBehind: (DrawScope.() -> Unit)?,
var onDrawBackdrop: DrawScope.(drawBackdrop: DrawScope.() -> Unit) -> Unit,
var onDrawSurface: (DrawScope.() -> Unit)?,
+ var onDrawFront: (DrawScope.() -> Unit)?,
var effects: BackdropEffectScope.() -> Unit
) : LayoutModifierNode, DrawModifierNode, GlobalPositionAwareModifierNode, ObserverModifierNode, Modifier.Node() {
@@ -249,6 +258,8 @@ private class DrawBackdropNode(
onDrawSurface?.invoke(this)
drawContent()
+
+ onDrawFront?.invoke(this)
}
override fun onGloballyPositioned(coordinates: LayoutCoordinates) {
diff --git a/catalog/release/baselineProfiles/0/catalog-release.dm b/catalog/release/baselineProfiles/0/catalog-release.dm
index ecbad5f..72aaf41 100644
Binary files a/catalog/release/baselineProfiles/0/catalog-release.dm and b/catalog/release/baselineProfiles/0/catalog-release.dm differ
diff --git a/catalog/release/baselineProfiles/1/catalog-release.dm b/catalog/release/baselineProfiles/1/catalog-release.dm
index dc35607..97a6cbc 100644
Binary files a/catalog/release/baselineProfiles/1/catalog-release.dm and b/catalog/release/baselineProfiles/1/catalog-release.dm differ
diff --git a/catalog/release/catalog-release.apk b/catalog/release/catalog-release.apk
index 6d80c53..5b95822 100644
Binary files a/catalog/release/catalog-release.apk and b/catalog/release/catalog-release.apk differ
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/BackdropDemoScaffold.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/BackdropDemoScaffold.kt
new file mode 100644
index 0000000..8458ce3
--- /dev/null
+++ b/catalog/src/main/java/com/kyant/backdrop/catalog/BackdropDemoScaffold.kt
@@ -0,0 +1,96 @@
+package com.kyant.backdrop.catalog
+
+import android.graphics.BitmapFactory
+import androidx.activity.compose.rememberLauncherForActivityResult
+import androidx.activity.result.PickVisualMediaRequest
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.annotation.DrawableRes
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.navigationBarsPadding
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.text.BasicText
+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.graphics.Color
+import androidx.compose.ui.graphics.asImageBitmap
+import androidx.compose.ui.graphics.painter.BitmapPainter
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import com.kyant.backdrop.Backdrop
+import com.kyant.backdrop.backdrop
+import com.kyant.backdrop.catalog.components.LiquidButton
+import com.kyant.backdrop.rememberBackdrop
+
+@Composable
+fun BackdropDemoScaffold(
+ modifier: Modifier = Modifier,
+ @DrawableRes initialPainterResId: Int = R.drawable.wallpaper_light,
+ content: @Composable (backdrop: Backdrop) -> Unit
+) {
+ Box(
+ Modifier.fillMaxSize(),
+ contentAlignment = Alignment.Center
+ ) {
+ var painter: Painter? by remember { mutableStateOf(null) }
+ val context = LocalContext.current
+ val pickMedia = rememberLauncherForActivityResult(
+ ActivityResultContracts.PickVisualMedia()
+ ) { uri ->
+ if (uri != null) {
+ try {
+ context.contentResolver.openInputStream(uri)?.use { inputStream ->
+ val imageBitmap = BitmapFactory.decodeStream(inputStream)?.asImageBitmap()
+ if (imageBitmap != null) {
+ painter = BitmapPainter(imageBitmap)
+ }
+ }
+ } catch (_: Exception) {
+ }
+ }
+ }
+
+ val backdrop = rememberBackdrop()
+
+ Image(
+ painter ?: painterResource(initialPainterResId),
+ null,
+ Modifier
+ .backdrop(backdrop)
+ .then(modifier)
+ .fillMaxSize(),
+ contentScale = ContentScale.Crop
+ )
+
+ content(backdrop)
+
+ LiquidButton(
+ { pickMedia.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)) },
+ backdrop,
+ Modifier
+ .padding(16f.dp)
+ .navigationBarsPadding()
+ .height(56f.dp)
+ .align(Alignment.BottomCenter),
+ tint = Color(0xFF0088FF)
+ ) {
+ BasicText(
+ "Pick an image",
+ Modifier.padding(horizontal = 8f.dp),
+ style = TextStyle(Color.White, 16f.sp)
+ )
+ }
+ }
+}
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/Block.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/Block.kt
new file mode 100644
index 0000000..0e94dcb
--- /dev/null
+++ b/catalog/src/main/java/com/kyant/backdrop/catalog/Block.kt
@@ -0,0 +1,8 @@
+package com.kyant.backdrop.catalog
+
+import androidx.compose.runtime.Composable
+
+@Composable
+fun Block(content: @Composable () -> Unit) {
+ content()
+}
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/CatalogDestination.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/CatalogDestination.kt
index c671d85..518d144 100644
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/CatalogDestination.kt
+++ b/catalog/src/main/java/com/kyant/backdrop/catalog/CatalogDestination.kt
@@ -2,12 +2,12 @@ package com.kyant.backdrop.catalog
enum class CatalogDestination {
Home,
+ Buttons,
+ Dialog,
GlassPlayground,
AdaptiveLuminanceGlass,
ControlCenter,
BottomTabs,
- IconButton,
- Dialog,
ScrollContainer,
LazyScrollContainer,
}
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/MainActivity.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/MainActivity.kt
index 3eba7b2..2a4a0c1 100644
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/MainActivity.kt
+++ b/catalog/src/main/java/com/kyant/backdrop/catalog/MainActivity.kt
@@ -8,8 +8,6 @@ import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.graphics.Color
import androidx.core.view.WindowCompat
-import com.kyant.backdrop.catalog.theme.LocalContentColor
-import com.kyant.backdrop.catalog.theme.ripple
class MainActivity : ComponentActivity() {
@@ -21,8 +19,7 @@ class MainActivity : ComponentActivity() {
val isLightTheme = !isSystemInDarkTheme()
CompositionLocalProvider(
- LocalContentColor provides if (isLightTheme) Color.Black else Color.White,
- LocalIndication provides ripple()
+ LocalIndication provides ripple(color = if (isLightTheme) Color.Black else Color.White)
) {
MainContent()
}
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/MainContent.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/MainContent.kt
index f1cd0f9..e218b5a 100644
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/MainContent.kt
+++ b/catalog/src/main/java/com/kyant/backdrop/catalog/MainContent.kt
@@ -8,11 +8,11 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import com.kyant.backdrop.catalog.destinations.AdaptiveLuminanceGlassContent
import com.kyant.backdrop.catalog.destinations.BottomTabsContent
+import com.kyant.backdrop.catalog.destinations.ButtonsContent
import com.kyant.backdrop.catalog.destinations.ControlCenterContent
import com.kyant.backdrop.catalog.destinations.DialogContent
import com.kyant.backdrop.catalog.destinations.GlassPlaygroundContent
import com.kyant.backdrop.catalog.destinations.HomeContent
-import com.kyant.backdrop.catalog.destinations.IconButtonContent
import com.kyant.backdrop.catalog.destinations.LazyScrollContainerContent
import com.kyant.backdrop.catalog.destinations.ScrollContainerContent
@@ -26,12 +26,15 @@ fun MainContent() {
when (destination) {
CatalogDestination.Home -> HomeContent(onNavigate = { destination = it })
+
+ CatalogDestination.Buttons -> ButtonsContent()
+ CatalogDestination.BottomTabs -> BottomTabsContent()
+ CatalogDestination.Dialog -> DialogContent()
+
+ CatalogDestination.ControlCenter -> ControlCenterContent()
+
CatalogDestination.GlassPlayground -> GlassPlaygroundContent()
CatalogDestination.AdaptiveLuminanceGlass -> AdaptiveLuminanceGlassContent()
- CatalogDestination.ControlCenter -> ControlCenterContent()
- CatalogDestination.BottomTabs -> BottomTabsContent()
- CatalogDestination.IconButton -> IconButtonContent()
- CatalogDestination.Dialog -> DialogContent()
CatalogDestination.ScrollContainer -> ScrollContainerContent()
CatalogDestination.LazyScrollContainer -> LazyScrollContainerContent()
}
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/theme/Ripple.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/Ripple.kt
similarity index 89%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/theme/Ripple.kt
rename to catalog/src/main/java/com/kyant/backdrop/catalog/Ripple.kt
index f106a71..bb02585 100644
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/theme/Ripple.kt
+++ b/catalog/src/main/java/com/kyant/backdrop/catalog/Ripple.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.kyant.backdrop.catalog.theme
+package com.kyant.backdrop.catalog
import androidx.compose.foundation.IndicationNodeFactory
import androidx.compose.foundation.interaction.InteractionSource
@@ -24,12 +24,10 @@ import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorProducer
-import androidx.compose.ui.graphics.isSpecified
import androidx.compose.ui.node.CompositionLocalConsumerModifierNode
import androidx.compose.ui.node.DelegatableNode
import androidx.compose.ui.node.DelegatingNode
import androidx.compose.ui.node.ObserverModifierNode
-import androidx.compose.ui.node.currentValueOf
import androidx.compose.ui.node.observeReads
import androidx.compose.ui.unit.Dp
@@ -100,6 +98,7 @@ private constructor(
private val colorProducer: ColorProducer?,
private val color: Color
) : IndicationNodeFactory {
+
constructor(
bounded: Boolean,
radius: Dp,
@@ -138,6 +137,7 @@ private class DelegatingThemeAwareRippleNode(
private val radius: Dp,
private val color: ColorProducer,
) : DelegatingNode(), CompositionLocalConsumerModifierNode, ObserverModifierNode {
+
private var rippleNode: DelegatableNode? = null
override fun onAttach() {
@@ -157,25 +157,14 @@ private class DelegatingThemeAwareRippleNode(
}
private fun attachNewRipple() {
- val calculateColor = ColorProducer {
- val userDefinedColor = color()
- if (userDefinedColor.isSpecified) {
- userDefinedColor
- } else {
- currentValueOf(LocalContentColor)
- }
- }
-
- val calculateRippleAlpha = { RippleDefaults.RippleAlpha }
-
rippleNode =
delegate(
createRippleModifierNode(
- interactionSource,
- bounded,
- radius,
- calculateColor,
- calculateRippleAlpha
+ interactionSource = interactionSource,
+ bounded = bounded,
+ radius = radius,
+ color = color,
+ rippleAlpha = { RippleDefaults.RippleAlpha }
)
)
}
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidButton.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidButton.kt
new file mode 100644
index 0000000..df4ed69
--- /dev/null
+++ b/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidButton.kt
@@ -0,0 +1,212 @@
+package com.kyant.backdrop.catalog.components
+
+import android.graphics.RuntimeShader
+import android.os.Build
+import androidx.compose.animation.core.Animatable
+import androidx.compose.animation.core.VectorConverter
+import androidx.compose.animation.core.VisibilityThreshold
+import androidx.compose.animation.core.spring
+import androidx.compose.foundation.LocalIndication
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.BlendMode
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.ShaderBrush
+import androidx.compose.ui.graphics.isSpecified
+import androidx.compose.ui.graphics.toArgb
+import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.util.fastCoerceAtMost
+import androidx.compose.ui.util.fastCoerceIn
+import androidx.compose.ui.util.lerp
+import com.kyant.backdrop.Backdrop
+import com.kyant.backdrop.catalog.utils.inspectDragGestures
+import com.kyant.backdrop.drawBackdrop
+import com.kyant.backdrop.effects.blur
+import com.kyant.backdrop.effects.refraction
+import com.kyant.backdrop.effects.saturation
+import com.kyant.capsule.ContinuousCapsule
+import kotlinx.coroutines.launch
+import kotlin.math.abs
+import kotlin.math.atan2
+import kotlin.math.cos
+import kotlin.math.sin
+import kotlin.math.tanh
+
+@Composable
+fun LiquidButton(
+ onClick: () -> Unit,
+ backdrop: Backdrop,
+ modifier: Modifier = Modifier,
+ isInteractive: Boolean = true,
+ tint: Color = Color.Unspecified,
+ surfaceColor: Color = Color.Unspecified,
+ content: @Composable RowScope.() -> Unit
+) {
+ val animationScope = rememberCoroutineScope()
+ val scaleProgressAnimation = remember { Animatable(0f) }
+ var pressStartPosition by remember { mutableStateOf(Offset.Zero) }
+ val offsetAnimation = remember { Animatable(Offset.Zero, Offset.VectorConverter) }
+
+ val interactiveHighlightShader = remember {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ RuntimeShader(
+ """
+uniform float2 size;
+layout(color) uniform half4 color;
+uniform float radius;
+uniform float2 offset;
+
+half4 main(float2 coord) {
+ float2 center = offset;
+ float dist = distance(coord, center);
+ float intensity = smoothstep(radius, radius * 0.5, dist);
+ return color * intensity;
+}"""
+ )
+ } else {
+ null
+ }
+ }
+
+ Row(
+ modifier
+ .drawBackdrop(
+ backdrop,
+ { ContinuousCapsule },
+ layer = if (isInteractive) {
+ {
+ val width = size.width
+ val height = size.height
+
+ val scaleProgress = scaleProgressAnimation.value
+ val maxScale = 0.1f
+ val scale = lerp(1f, 1f + maxScale, scaleProgress)
+
+ val maxOffset = size.minDimension
+ val initialDerivative = 0.05f
+ val offset = offsetAnimation.value
+ translationX = maxOffset * tanh(initialDerivative * offset.x / maxOffset)
+ translationY = maxOffset * tanh(initialDerivative * offset.y / maxOffset)
+
+ val maxDragScale = 0.1f
+ val offsetAngle = atan2(offset.y, offset.x)
+ scaleX =
+ scale +
+ maxDragScale * abs(cos(offsetAngle) * offset.x / size.maxDimension) *
+ (width / height).fastCoerceAtMost(1f)
+ scaleY =
+ scale +
+ maxDragScale * abs(sin(offsetAngle) * offset.y / size.maxDimension) *
+ (height / width).fastCoerceAtMost(1f)
+ }
+ } else {
+ null
+ },
+ onDrawSurface = {
+ if (tint.isSpecified) {
+ drawRect(tint, blendMode = BlendMode.Hue)
+ drawRect(tint.copy(alpha = 0.75f))
+ }
+ if (surfaceColor.isSpecified) {
+ drawRect(surfaceColor)
+ }
+ },
+ onDrawFront = if (isInteractive) {
+ {
+ val progress = scaleProgressAnimation.value.fastCoerceIn(0f, 1f)
+ if (progress > 0f) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && interactiveHighlightShader != null) {
+ drawRect(
+ Color.White.copy(0.1f * progress),
+ blendMode = BlendMode.Plus
+ )
+ interactiveHighlightShader.apply {
+ val offset = pressStartPosition + offsetAnimation.value
+ setFloatUniform("size", size.width, size.height)
+ setColorUniform("color", Color.White.copy(0.15f * progress).toArgb())
+ setFloatUniform("radius", size.maxDimension)
+ setFloatUniform(
+ "offset",
+ offset.x.fastCoerceIn(0f, size.width),
+ offset.y.fastCoerceIn(0f, size.height)
+ )
+ }
+ drawRect(
+ ShaderBrush(interactiveHighlightShader),
+ blendMode = BlendMode.Plus
+ )
+ } else {
+ drawRect(
+ Color.White.copy(0.25f * progress),
+ blendMode = BlendMode.Plus
+ )
+ }
+ }
+ }
+ } else {
+ null
+ }
+ ) {
+ saturation()
+ blur(2f.dp.toPx())
+ refraction(12f.dp.toPx(), 24f.dp.toPx())
+ }
+ .clickable(
+ interactionSource = null,
+ indication = if (isInteractive) null else LocalIndication.current,
+ role = Role.Button,
+ onClick = onClick
+ )
+ .then(
+ if (isInteractive) {
+ Modifier.pointerInput(animationScope) {
+ val progressAnimationSpec = spring(0.5f, 300f, 0.001f)
+ val offsetAnimationSpec = spring(1f, 300f, Offset.VisibilityThreshold)
+ val onDragStop: () -> Unit = {
+ animationScope.launch {
+ launch { scaleProgressAnimation.animateTo(0f, progressAnimationSpec) }
+ launch { offsetAnimation.animateTo(Offset.Zero, offsetAnimationSpec) }
+ }
+ }
+ inspectDragGestures(
+ onDragStart = { down ->
+ pressStartPosition = down.position
+ animationScope.launch {
+ launch { scaleProgressAnimation.animateTo(1f, progressAnimationSpec) }
+ launch { offsetAnimation.snapTo(Offset.Zero) }
+ }
+ },
+ onDragEnd = { onDragStop() },
+ onDragCancel = onDragStop
+ ) { _, dragAmount ->
+ animationScope.launch {
+ offsetAnimation.snapTo(offsetAnimation.value + dragAmount)
+ }
+ }
+ }
+ } else {
+ Modifier
+ }
+ )
+ .height(48f.dp)
+ .padding(horizontal = 16f.dp),
+ horizontalArrangement = Arrangement.spacedBy(8f.dp, Alignment.CenterHorizontally),
+ verticalAlignment = Alignment.CenterVertically,
+ content = content
+ )
+}
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/components/Text.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/components/Text.kt
deleted file mode 100644
index 7490cc2..0000000
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/components/Text.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.kyant.backdrop.catalog.components
-
-import androidx.compose.foundation.text.BasicText
-import androidx.compose.foundation.text.TextAutoSize
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.ColorProducer
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.style.TextOverflow
-import com.kyant.backdrop.catalog.theme.LocalContentColor
-
-const val LoremIpsum: String =
- """Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."""
-
-@Composable
-fun Text(
- text: String,
- style: TextStyle,
- modifier: Modifier = Modifier,
- color: Color = LocalContentColor.current,
- overflow: TextOverflow = TextOverflow.Ellipsis,
- softWrap: Boolean = true,
- maxLines: Int = Int.MAX_VALUE,
- minLines: Int = 1,
- autoSize: TextAutoSize? = null,
-) {
- BasicText(
- text = text,
- modifier = modifier,
- style = style,
- overflow = overflow,
- softWrap = softWrap,
- maxLines = maxLines,
- minLines = minLines,
- color = { color },
- autoSize = autoSize
- )
-}
-
-@Composable
-fun Text(
- text: () -> String,
- style: TextStyle,
- color: ColorProducer,
- modifier: Modifier = Modifier,
- overflow: TextOverflow = TextOverflow.Ellipsis,
- softWrap: Boolean = true,
- maxLines: Int = Int.MAX_VALUE,
- minLines: Int = 1,
- autoSize: TextAutoSize? = null,
-) {
- BasicText(
- text = text(),
- modifier = modifier,
- style = style,
- overflow = overflow,
- softWrap = softWrap,
- maxLines = maxLines,
- minLines = minLines,
- color = color,
- autoSize = autoSize
- )
-}
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/AdaptiveLuminanceGlassContent.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/AdaptiveLuminanceGlassContent.kt
index 27f2116..185b923 100644
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/AdaptiveLuminanceGlassContent.kt
+++ b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/AdaptiveLuminanceGlassContent.kt
@@ -11,6 +11,7 @@ import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
@@ -25,14 +26,15 @@ import androidx.compose.ui.graphics.rememberGraphicsLayer
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
import androidx.compose.ui.util.lerp
import androidx.core.graphics.scale
import com.kyant.backdrop.backdrop
+import com.kyant.backdrop.catalog.Block
import com.kyant.backdrop.catalog.R
-import com.kyant.backdrop.catalog.components.Text
-import com.kyant.backdrop.catalog.theme.TextStyles
import com.kyant.backdrop.drawBackdrop
import com.kyant.backdrop.effects.blur
import com.kyant.backdrop.effects.colorFilter
@@ -112,7 +114,7 @@ fun AdaptiveLuminanceGlassContent() {
.drawBackdrop(
backdrop,
{ ContinuousRoundedRectangle(24f.dp) },
- layerBlock = {
+ layer = {
val offset = offsetAnimation.value
val zoom = zoomAnimation.value
val rotation = rotationAnimation.value
@@ -172,11 +174,13 @@ fun AdaptiveLuminanceGlassContent() {
.align(Alignment.Center),
contentAlignment = Alignment.Center
) {
- Text(
- { "luminance:\n${"%.2f".format(luminanceAnimation.value)}" },
- TextStyles.body.copy(textAlign = TextAlign.Center),
- color = { contentColorAnimation.value }
- )
+ Block {
+ BasicText(
+ "luminance:\n${"%.2f".format(luminanceAnimation.value)}",
+ style = TextStyle(Color.Unspecified, 16f.sp, textAlign = TextAlign.Center),
+ color = { contentColorAnimation.value }
+ )
+ }
}
}
}
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/BottomTabsContent.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/BottomTabsContent.kt
index d825156..f0027fa 100644
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/BottomTabsContent.kt
+++ b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/BottomTabsContent.kt
@@ -2,7 +2,6 @@ package com.kyant.backdrop.catalog.destinations
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.spring
-import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.draggable
@@ -13,11 +12,11 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
-import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
@@ -35,7 +34,6 @@ import androidx.compose.ui.graphics.CompositingStrategy
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.graphics.layer.drawLayer
import androidx.compose.ui.graphics.rememberGraphicsLayer
-import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.layout
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.semantics.clearAndSetSemantics
@@ -49,13 +47,12 @@ import androidx.compose.ui.util.fastCoerceIn
import androidx.compose.ui.util.fastRoundToInt
import androidx.compose.ui.util.lerp
import com.kyant.backdrop.backdrop
+import com.kyant.backdrop.catalog.BackdropDemoScaffold
import com.kyant.backdrop.catalog.R
-import com.kyant.backdrop.catalog.components.Text
-import com.kyant.backdrop.catalog.theme.LocalContentColor
import com.kyant.backdrop.drawBackdrop
import com.kyant.backdrop.effects.blur
+import com.kyant.backdrop.effects.dispersion
import com.kyant.backdrop.effects.refraction
-import com.kyant.backdrop.effects.refractionWithDispersion
import com.kyant.backdrop.effects.saturation
import com.kyant.backdrop.highlight.Highlight
import com.kyant.backdrop.rememberBackdrop
@@ -66,6 +63,7 @@ import kotlinx.coroutines.launch
@Composable
fun BottomTabsContent() {
val isLightTheme = !isSystemInDarkTheme()
+ val contentColor = if (isLightTheme) Color.Black else Color.White
val accentColor =
if (isLightTheme) Color(0xFF0088FF)
else Color(0xFF0091FF)
@@ -74,9 +72,8 @@ fun BottomTabsContent() {
else Color(0xFF121212).copy(0.4f)
val airplaneModeIcon = painterResource(R.drawable.flight_40px)
- val iconColorFilter = ColorFilter.tint(LocalContentColor.current)
+ val iconColorFilter = ColorFilter.tint(contentColor)
- val backdrop = rememberBackdrop()
val tabsBackdrop = rememberBackdrop()
val tabsLayer =
rememberGraphicsLayer().apply {
@@ -89,20 +86,9 @@ fun BottomTabsContent() {
val scaleYAnimation = remember { Animatable(0f) }
val tabOffsetAnimation = remember { Animatable(0f) }
- Box(Modifier.fillMaxSize()) {
- Image(
- painterResource(R.drawable.system_home_screen_light),
- null,
- Modifier
- .backdrop(backdrop)
- .fillMaxSize(),
- contentScale = ContentScale.Crop
- )
-
+ BackdropDemoScaffold { backdrop ->
Box(
- Modifier
- .padding(40f.dp)
- .align(Alignment.Center),
+ Modifier.padding(40f.dp),
contentAlignment = Alignment.CenterStart
) {
Box(
@@ -131,7 +117,7 @@ fun BottomTabsContent() {
.drawBackdrop(
backdrop,
{ ContinuousCapsule },
- layerBlock = {
+ layer = {
val progress = pressAnimation.value
val scale = lerp(1f, 1f + 2f.dp.toPx() / size.height, progress)
scaleX = scale
@@ -167,9 +153,9 @@ fun BottomTabsContent() {
.size(28f.dp)
.paint(airplaneModeIcon, colorFilter = iconColorFilter)
)
- Text(
+ BasicText(
"Tab ${index + 1}",
- TextStyle(fontSize = 12f.sp)
+ style = TextStyle(contentColor, 12f.sp)
)
}
}
@@ -263,7 +249,7 @@ fun BottomTabsContent() {
offset = DpOffset(0f.dp, 4f.dp * progress)
)
},
- layerBlock = {
+ layer = {
translationX = tabOffsetAnimation.value.fastCoerceIn(0f, size.width * 3)
scaleX = lerp(1f, 1f + 20f.dp.toPx() / size.height, scaleXAnimation.value)
scaleY = lerp(1f, 1f + 20f.dp.toPx() / size.height, scaleYAnimation.value)
@@ -278,10 +264,14 @@ fun BottomTabsContent() {
}
) {
val progress = pressAnimation.value
- refractionWithDispersion(
+ refraction(
12f.dp.toPx() * progress,
12f.dp.toPx() * progress
)
+ dispersion(
+ 12f.dp.toPx() * progress,
+ 24f.dp.toPx() * progress
+ )
}
.draggable(
rememberDraggableState { delta ->
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ButtonsContent.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ButtonsContent.kt
new file mode 100644
index 0000000..27e0d82
--- /dev/null
+++ b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ButtonsContent.kt
@@ -0,0 +1,63 @@
+package com.kyant.backdrop.catalog.destinations
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.text.BasicText
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import com.kyant.backdrop.catalog.BackdropDemoScaffold
+import com.kyant.backdrop.catalog.components.LiquidButton
+
+@Composable
+fun ButtonsContent() {
+ BackdropDemoScaffold { backdrop ->
+ Column(
+ horizontalAlignment = Alignment.CenterHorizontally,
+ verticalArrangement = Arrangement.spacedBy(16f.dp)
+ ) {
+ LiquidButton(
+ {},
+ backdrop
+ ) {
+ BasicText(
+ "Transparent Liquid Button",
+ style = TextStyle(Color.Black, 15f.sp)
+ )
+ }
+ LiquidButton(
+ {},
+ backdrop,
+ surfaceColor = Color.White.copy(0.3f)
+ ) {
+ BasicText(
+ "Surface Liquid Button",
+ style = TextStyle(Color.Black, 15f.sp)
+ )
+ }
+ LiquidButton(
+ {},
+ backdrop,
+ tint = Color(0xFF0088FF)
+ ) {
+ BasicText(
+ "Tinted Liquid Button",
+ style = TextStyle(Color.White, 15f.sp)
+ )
+ }
+ LiquidButton(
+ {},
+ backdrop,
+ tint = Color(0xFFFF8D28)
+ ) {
+ BasicText(
+ "Tinted Liquid Button",
+ style = TextStyle(Color.White, 15f.sp)
+ )
+ }
+ }
+ }
+}
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ControlCenterContent.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ControlCenterContent.kt
index da2fcf2..91f0ef7 100644
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ControlCenterContent.kt
+++ b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ControlCenterContent.kt
@@ -3,7 +3,6 @@ package com.kyant.backdrop.catalog.destinations
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.EaseIn
import androidx.compose.animation.core.spring
-import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.Orientation
@@ -21,7 +20,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
@@ -32,7 +30,6 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.draw.paint
import androidx.compose.ui.draw.scale
-import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.BlurEffect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
@@ -40,7 +37,6 @@ import androidx.compose.ui.graphics.GraphicsLayerScope
import androidx.compose.ui.graphics.TransformOrigin
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.graphicsLayer
-import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.layout
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
@@ -49,18 +45,16 @@ import androidx.compose.ui.util.fastCoerceIn
import androidx.compose.ui.util.fastRoundToInt
import androidx.compose.ui.util.lerp
import com.kyant.backdrop.BackdropEffectScope
-import com.kyant.backdrop.backdrop
-import com.kyant.backdrop.catalog.ProgressConverter
+import com.kyant.backdrop.catalog.BackdropDemoScaffold
import com.kyant.backdrop.catalog.R
-import com.kyant.backdrop.catalog.rememberUISensor
-import com.kyant.backdrop.catalog.theme.LocalContentColor
+import com.kyant.backdrop.catalog.utils.ProgressConverter
+import com.kyant.backdrop.catalog.utils.rememberUISensor
import com.kyant.backdrop.contentBackdrop
import com.kyant.backdrop.drawBackdrop
import com.kyant.backdrop.effects.refraction
import com.kyant.backdrop.effects.saturation
import com.kyant.backdrop.highlight.Highlight
import com.kyant.backdrop.highlight.HighlightStyle
-import com.kyant.backdrop.rememberBackdrop
import com.kyant.capsule.ContinuousCapsule
import com.kyant.capsule.ContinuousRoundedRectangle
import kotlinx.coroutines.launch
@@ -104,7 +98,6 @@ fun ControlCenterContent() {
}
val maxDragHeight = 1000f
- val backdrop = rememberBackdrop()
val uiSensor = rememberUISensor()
val glassShape = { itemShape }
val glassHighlight = { Highlight { HighlightStyle.Dynamic(angle = uiSensor.gravityAngle) } }
@@ -134,217 +127,154 @@ fun ControlCenterContent() {
}
}
- CompositionLocalProvider(LocalContentColor provides Color.White) {
- Box(
+ val backdropModifier = Modifier
+ .draggable(
+ rememberDraggableState { delta ->
+ val targetProgress = enterProgressAnimation.value + delta / maxDragHeight
+ animationScope.launch {
+ launch {
+ enterProgressAnimation.snapTo(targetProgress)
+ }
+ launch {
+ safeEnterProgressAnimation.snapTo(targetProgress.fastCoerceIn(0f, 1f))
+ }
+ }
+ },
+ Orientation.Vertical,
+ onDragStopped = { velocity ->
+ val targetProgress = when {
+ velocity < 0f -> 0f
+ velocity > 0f -> 1f
+ else -> if (enterProgressAnimation.value < 0.5f) 0f else 1f
+ }
+ animationScope.launch {
+ launch {
+ enterProgressAnimation.animateTo(
+ targetProgress,
+ if (targetProgress > 0.5f) {
+ spring(0.5f, 300f, 0.5f / maxDragHeight)
+ } else {
+ spring(1f, 300f, 0.01f)
+ },
+ velocity / maxDragHeight
+ )
+ }
+ launch {
+ safeEnterProgressAnimation.animateTo(
+ targetProgress,
+ spring(1f, 300f, 0.01f)
+ )
+ }
+ }
+ }
+ )
+ .drawWithContent {
+ val progress = safeEnterProgressAnimation.value
+
+ drawContent()
+ drawRect(dimColor.copy(dimColor.alpha * progress))
+ }
+ .graphicsLayer {
+ val progress = safeEnterProgressAnimation.value
+
+ val blurRadius = 4f.dp.toPx() * progress
+ if (blurRadius > 0f) {
+ renderEffect = BlurEffect(blurRadius, blurRadius)
+ }
+ }
+
+ BackdropDemoScaffold(
+ backdropModifier,
+ initialPainterResId = R.drawable.system_home_screen_light
+ ) { backdrop ->
+ Column(
Modifier
- .draggable(
- rememberDraggableState { delta ->
- val targetProgress = enterProgressAnimation.value + delta / maxDragHeight
- animationScope.launch {
- launch {
- enterProgressAnimation.snapTo(targetProgress)
- }
- launch {
- safeEnterProgressAnimation.snapTo(targetProgress.fastCoerceIn(0f, 1f))
- }
- }
- },
- Orientation.Vertical,
- onDragStopped = { velocity ->
- val targetProgress = when {
- velocity < 0f -> 0f
- velocity > 0f -> 1f
- else -> if (enterProgressAnimation.value < 0.5f) 0f else 1f
- }
- animationScope.launch {
- launch {
- enterProgressAnimation.animateTo(
- targetProgress,
- if (targetProgress > 0.5f) {
- spring(0.5f, 300f, 0.5f / maxDragHeight)
- } else {
- spring(1f, 300f, 0.01f)
- },
- velocity / maxDragHeight
- )
- }
- launch {
- safeEnterProgressAnimation.animateTo(
- targetProgress,
- spring(1f, 300f, 0.01f)
- )
- }
- }
- }
- )
- .fillMaxSize()
+ .padding(top = 80f.dp)
+ .systemBarsPadding()
+ .displayCutoutPadding()
+ .fillMaxSize(),
+ horizontalAlignment = Alignment.CenterHorizontally
) {
- Image(
- painterResource(R.drawable.system_home_screen_light),
- null,
- Modifier
- .backdrop(backdrop)
- .drawWithContent {
- val progress = safeEnterProgressAnimation.value
-
- drawContent()
- drawRect(dimColor.copy(dimColor.alpha * progress))
- }
- .graphicsLayer {
- val progress = safeEnterProgressAnimation.value
-
- val blurRadius = 4f.dp.toPx() * progress
- if (blurRadius > 0f) {
- renderEffect = BlurEffect(blurRadius, blurRadius)
- }
- }
- .fillMaxSize(),
- contentScale = ContentScale.Crop
- )
-
- Column(
- Modifier
- .padding(top = 80f.dp)
- .systemBarsPadding()
- .displayCutoutPadding()
- .fillMaxSize(),
- horizontalAlignment = Alignment.CenterHorizontally
+ Row(
+ horizontalArrangement = Arrangement.spacedBy(itemSpacing),
+ verticalAlignment = Alignment.CenterVertically
) {
- Row(
- horizontalArrangement = Arrangement.spacedBy(itemSpacing),
- verticalAlignment = Alignment.CenterVertically
+ Box(
+ Modifier
+ .drawBackdrop(
+ backdrop,
+ { ContinuousRoundedRectangle(40f.dp) },
+ layer = glassLayer,
+ highlight = null,
+ shadow = null,
+ onDrawSurface = glassSurface,
+ effects = glassEffects
+ )
+ .contentBackdrop(
+ { ContinuousRoundedRectangle(40f.dp) },
+ highlight = glassHighlight,
+ shadow = null
+ ) {
+ refraction(12f.dp.toPx(), size.minDimension / 4f, true)
+ }
+ .size(itemTwoSpanSize)
+ .padding(itemSpacing)
) {
Box(
Modifier
- .drawBackdrop(
- backdrop,
- { ContinuousRoundedRectangle(40f.dp) },
- layerBlock = {
- glassLayer()
- },
- highlight = null,
- shadow = null,
- onDrawSurface = glassSurface,
- effects = glassEffects
- )
- .contentBackdrop(
- { ContinuousRoundedRectangle(40f.dp) },
- highlight = glassHighlight,
- shadow = null
- ) {
- refraction(12f.dp.toPx(), size.minDimension / 4f, true)
- }
- .size(itemTwoSpanSize)
- .padding(itemSpacing)
- ) {
- Box(
- Modifier
- .clip(innerItemShape)
- .background(inactiveItemColor)
- .clickable {}
- .scale(innerItemIconScale)
- .paint(airplaneModeIcon, colorFilter = iconColorFilter)
- .size(innerItemSize)
- .align(Alignment.TopStart)
- )
- Box(
- Modifier
- .clip(innerItemShape)
- .background(activeItemColor)
- .clickable {}
- .scale(innerItemIconScale)
- .paint(airplaneModeIcon, colorFilter = iconColorFilter)
- .size(innerItemSize)
- .align(Alignment.TopEnd)
- )
- Box(
- Modifier
- .clip(innerItemShape)
- .background(activeItemColor)
- .clickable {}
- .scale(innerItemIconScale)
- .paint(airplaneModeIcon, colorFilter = iconColorFilter)
- .size(innerItemSize)
- .align(Alignment.BottomStart)
- )
- }
+ .clip(innerItemShape)
+ .background(inactiveItemColor)
+ .clickable {}
+ .scale(innerItemIconScale)
+ .paint(airplaneModeIcon, colorFilter = iconColorFilter)
+ .size(innerItemSize)
+ .align(Alignment.TopStart)
+ )
Box(
Modifier
- .drawBackdrop(
- backdrop,
- glassShape,
- layerBlock = glassLayer,
- highlight = glassHighlight,
- shadow = null,
- onDrawSurface = glassSurface,
- effects = glassEffects
- )
- .size(itemTwoSpanSize)
+ .clip(innerItemShape)
+ .background(activeItemColor)
+ .clickable {}
+ .scale(innerItemIconScale)
+ .paint(airplaneModeIcon, colorFilter = iconColorFilter)
+ .size(innerItemSize)
+ .align(Alignment.TopEnd)
+ )
+ Box(
+ Modifier
+ .clip(innerItemShape)
+ .background(activeItemColor)
+ .clickable {}
+ .scale(innerItemIconScale)
+ .paint(airplaneModeIcon, colorFilter = iconColorFilter)
+ .size(innerItemSize)
+ .align(Alignment.BottomStart)
)
}
-
- Spacer(spacerLayoutModifier)
-
- Row(
- horizontalArrangement = Arrangement.spacedBy(itemSpacing, Alignment.CenterHorizontally),
- verticalAlignment = Alignment.CenterVertically
- ) {
- Column(
- verticalArrangement = Arrangement.spacedBy(itemSpacing)
- ) {
- Row(
- horizontalArrangement = Arrangement.spacedBy(itemSpacing),
- verticalAlignment = Alignment.CenterVertically
- ) {
- Box(
- Modifier
- .drawBackdrop(
- backdrop,
- glassShape,
- layerBlock = glassLayer,
- highlight = glassHighlight,
- shadow = null,
- onDrawSurface = glassSurface,
- effects = glassEffects
- )
- .clickable {}
- .paint(airplaneModeIcon, colorFilter = iconColorFilter)
- .size(itemSize)
- )
- Box(
- Modifier
- .drawBackdrop(
- backdrop,
- glassShape,
- layerBlock = glassLayer,
- highlight = glassHighlight,
- shadow = null,
- onDrawSurface = glassSurface,
- effects = glassEffects
- )
- .clickable {}
- .paint(airplaneModeIcon, colorFilter = iconColorFilter)
- .size(itemSize)
- )
- }
- Box(
- Modifier
- .drawBackdrop(
- backdrop,
- glassShape,
- layerBlock = glassLayer,
- highlight = glassHighlight,
- shadow = null,
- onDrawSurface = {
- drawRect(accentColor, blendMode = BlendMode.Hue)
- drawRect(accentColor.copy(0.6f))
- },
- effects = glassEffects
- )
- .size(itemTwoSpanSize, itemSize)
+ Box(
+ Modifier
+ .drawBackdrop(
+ backdrop,
+ glassShape,
+ layer = glassLayer,
+ highlight = glassHighlight,
+ shadow = null,
+ onDrawSurface = glassSurface,
+ effects = glassEffects
)
- }
+ .size(itemTwoSpanSize)
+ )
+ }
+ Spacer(spacerLayoutModifier)
+
+ Row(
+ horizontalArrangement = Arrangement.spacedBy(itemSpacing, Alignment.CenterHorizontally),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Column(
+ verticalArrangement = Arrangement.spacedBy(itemSpacing)
+ ) {
Row(
horizontalArrangement = Arrangement.spacedBy(itemSpacing),
verticalAlignment = Alignment.CenterVertically
@@ -354,32 +284,46 @@ fun ControlCenterContent() {
.drawBackdrop(
backdrop,
glassShape,
- layerBlock = glassLayer,
+ layer = glassLayer,
highlight = glassHighlight,
shadow = null,
onDrawSurface = glassSurface,
effects = glassEffects
)
- .size(itemSize, itemTwoSpanSize)
+ .clickable {}
+ .paint(airplaneModeIcon, colorFilter = iconColorFilter)
+ .size(itemSize)
)
Box(
Modifier
.drawBackdrop(
backdrop,
glassShape,
- layerBlock = glassLayer,
+ layer = glassLayer,
highlight = glassHighlight,
shadow = null,
onDrawSurface = glassSurface,
effects = glassEffects
)
- .size(itemSize, itemTwoSpanSize)
+ .clickable {}
+ .paint(airplaneModeIcon, colorFilter = iconColorFilter)
+ .size(itemSize)
)
}
+ Box(
+ Modifier
+ .drawBackdrop(
+ backdrop,
+ glassShape,
+ layer = glassLayer,
+ highlight = glassHighlight,
+ shadow = null,
+ effects = glassEffects
+ )
+ .size(itemTwoSpanSize, itemSize)
+ )
}
- Spacer(spacerLayoutModifier)
-
Row(
horizontalArrangement = Arrangement.spacedBy(itemSpacing),
verticalAlignment = Alignment.CenterVertically
@@ -389,73 +333,107 @@ fun ControlCenterContent() {
.drawBackdrop(
backdrop,
glassShape,
- layerBlock = glassLayer,
+ layer = glassLayer,
highlight = glassHighlight,
shadow = null,
onDrawSurface = glassSurface,
effects = glassEffects
)
- .size(itemTwoSpanSize)
+ .size(itemSize, itemTwoSpanSize)
)
+ Box(
+ Modifier
+ .drawBackdrop(
+ backdrop,
+ glassShape,
+ layer = glassLayer,
+ highlight = glassHighlight,
+ shadow = null,
+ onDrawSurface = glassSurface,
+ effects = glassEffects
+ )
+ .size(itemSize, itemTwoSpanSize)
+ )
+ }
+ }
- Column(
- verticalArrangement = Arrangement.spacedBy(itemSpacing)
+ Spacer(spacerLayoutModifier)
+
+ Row(
+ horizontalArrangement = Arrangement.spacedBy(itemSpacing),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Box(
+ Modifier
+ .drawBackdrop(
+ backdrop,
+ glassShape,
+ layer = glassLayer,
+ highlight = glassHighlight,
+ shadow = null,
+ onDrawSurface = glassSurface,
+ effects = glassEffects
+ )
+ .size(itemTwoSpanSize)
+ )
+
+ Column(
+ verticalArrangement = Arrangement.spacedBy(itemSpacing)
+ ) {
+ Row(
+ horizontalArrangement = Arrangement.spacedBy(itemSpacing),
+ verticalAlignment = Alignment.CenterVertically
) {
- Row(
- horizontalArrangement = Arrangement.spacedBy(itemSpacing),
- verticalAlignment = Alignment.CenterVertically
- ) {
- Box(
- Modifier
- .drawBackdrop(
- backdrop,
- glassShape,
- layerBlock = glassLayer,
- highlight = glassHighlight,
- shadow = null,
- onDrawSurface = glassSurface,
- effects = glassEffects
- )
- .clickable {}
- .paint(airplaneModeIcon, colorFilter = iconColorFilter)
- .size(itemSize)
- )
- Box(
- Modifier
- .drawBackdrop(
- backdrop,
- glassShape,
- layerBlock = glassLayer,
- highlight = glassHighlight,
- shadow = null,
- onDrawSurface = glassSurface,
- effects = glassEffects
- )
- .clickable {}
- .paint(airplaneModeIcon, colorFilter = iconColorFilter)
- .size(itemSize)
- )
- }
- Row(
- horizontalArrangement = Arrangement.spacedBy(itemSpacing),
- verticalAlignment = Alignment.CenterVertically
- ) {
- Box(
- Modifier
- .drawBackdrop(
- backdrop,
- glassShape,
- layerBlock = glassLayer,
- highlight = glassHighlight,
- shadow = null,
- onDrawSurface = glassSurface,
- effects = glassEffects
- )
- .clickable {}
- .paint(airplaneModeIcon, colorFilter = iconColorFilter)
- .size(itemSize)
- )
- }
+ Box(
+ Modifier
+ .drawBackdrop(
+ backdrop,
+ glassShape,
+ layer = glassLayer,
+ highlight = glassHighlight,
+ shadow = null,
+ onDrawSurface = glassSurface,
+ effects = glassEffects
+ )
+ .clickable {}
+ .paint(airplaneModeIcon, colorFilter = iconColorFilter)
+ .size(itemSize)
+ )
+ Box(
+ Modifier
+ .drawBackdrop(
+ backdrop,
+ glassShape,
+ layer = glassLayer,
+ highlight = glassHighlight,
+ shadow = null,
+ onDrawSurface = glassSurface,
+ effects = glassEffects
+ )
+ .clickable {}
+ .paint(airplaneModeIcon, colorFilter = iconColorFilter)
+ .size(itemSize)
+ )
+ }
+ Row(
+ horizontalArrangement = Arrangement.spacedBy(itemSpacing),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Box(
+ Modifier
+ .drawBackdrop(
+ backdrop,
+ glassShape,
+ layer = glassLayer,
+ highlight = glassHighlight,
+ shadow = null,
+ onDrawSurface = glassSurface,
+ effects = glassEffects
+ )
+ .clickable {}
+ .paint(airplaneModeIcon, colorFilter = iconColorFilter)
+ .size(itemSize)
+ )
}
}
}
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/DialogContent.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/DialogContent.kt
index b5b9ac9..4ad8142 100644
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/DialogContent.kt
+++ b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/DialogContent.kt
@@ -1,6 +1,5 @@
package com.kyant.backdrop.catalog.destinations
-import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.isSystemInDarkTheme
@@ -12,40 +11,33 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
-import androidx.compose.ui.draw.drawWithCache
-import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
-import androidx.compose.ui.graphics.layer.drawLayer
-import androidx.compose.ui.layout.ContentScale
-import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
-import com.kyant.backdrop.backdrop
+import com.kyant.backdrop.catalog.BackdropDemoScaffold
import com.kyant.backdrop.catalog.R
-import com.kyant.backdrop.catalog.components.LoremIpsum
-import com.kyant.backdrop.catalog.components.Text
-import com.kyant.backdrop.catalog.theme.LocalContentColor
import com.kyant.backdrop.drawBackdrop
import com.kyant.backdrop.effects.blur
import com.kyant.backdrop.effects.colorFilter
import com.kyant.backdrop.effects.refraction
import com.kyant.backdrop.highlight.Highlight
import com.kyant.backdrop.highlight.HighlightStyle
-import com.kyant.backdrop.rememberBackdrop
import com.kyant.capsule.ContinuousCapsule
import com.kyant.capsule.ContinuousRoundedRectangle
@Composable
fun DialogContent() {
val isLightTheme = !isSystemInDarkTheme()
+ val contentColor = if (isLightTheme) Color.Black else Color.White
val accentColor =
if (isLightTheme) Color(0xFF0088FF)
else Color(0xFF0091FF)
@@ -56,20 +48,13 @@ fun DialogContent() {
if (isLightTheme) Color(0xFF29293A).copy(0.23f)
else Color(0xFF121212).copy(0.56f)
- val backdrop = rememberBackdrop()
-
- Box(Modifier.fillMaxSize()) {
- Image(
- painterResource(R.drawable.system_home_screen_light),
- null,
+ BackdropDemoScaffold(
+ initialPainterResId = R.drawable.system_home_screen_light
+ ) { backdrop ->
+ Box(
Modifier
- .backdrop(backdrop)
- .drawWithContent {
- drawContent()
- drawRect(dimColor)
- }
- .fillMaxSize(),
- contentScale = ContentScale.Crop
+ .background(dimColor)
+ .fillMaxSize()
)
Column(
@@ -89,49 +74,27 @@ fun DialogContent() {
refraction(24f.dp.toPx(), 48f.dp.toPx(), true)
}
.fillMaxWidth()
- .align(Alignment.Center)
) {
- Text(
+ BasicText(
"Dialog Title",
- TextStyle(fontSize = 24f.sp, fontWeight = FontWeight.Medium),
- Modifier.padding(28f.dp, 24f.dp, 28f.dp, 12f.dp)
+ Modifier.padding(28f.dp, 24f.dp, 28f.dp, 12f.dp),
+ style = TextStyle(contentColor, 24f.sp, FontWeight.Medium)
)
- Text(
+ BasicText(
LoremIpsum,
- TextStyle(fontSize = 15f.sp),
Modifier
.then(
if (isLightTheme) {
// plus darker
Modifier
- .drawWithCache {
- val bottomLayer = obtainGraphicsLayer().apply {
- blendMode = BlendMode.Overlay
- }
- val topLayer = obtainGraphicsLayer().apply {
- blendMode = BlendMode.Luminosity
- }
-
- onDrawWithContent {
- bottomLayer.record {
- this@onDrawWithContent.drawContent()
- }
- topLayer.record {
- this@onDrawWithContent.drawContent()
- }
-
- drawLayer(bottomLayer)
- drawLayer(topLayer)
- }
- }
} else {
// plus lighter
Modifier.graphicsLayer(blendMode = BlendMode.Plus)
}
)
.padding(24f.dp, 12f.dp, 24f.dp, 12f.dp),
- color = LocalContentColor.current.copy(0.68f),
+ style = TextStyle(contentColor.copy(0.68f), 15f.sp),
maxLines = 5
)
@@ -153,9 +116,9 @@ fun DialogContent() {
horizontalArrangement = Arrangement.spacedBy(4f.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically
) {
- Text(
+ BasicText(
"Cancel",
- TextStyle(fontSize = 16f.sp)
+ style = TextStyle(contentColor, 16f.sp)
)
}
Row(
@@ -169,13 +132,15 @@ fun DialogContent() {
horizontalArrangement = Arrangement.spacedBy(4f.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically
) {
- Text(
+ BasicText(
"Okay",
- TextStyle(fontSize = 16f.sp),
- color = Color.White
+ style = TextStyle(Color.White, 16f.sp)
)
}
}
}
}
}
+
+private const val LoremIpsum =
+ """Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."""
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/GlassPlaygroundContent.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/GlassPlaygroundContent.kt
index ccaccb4..ce7cb05 100644
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/GlassPlaygroundContent.kt
+++ b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/GlassPlaygroundContent.kt
@@ -2,16 +2,13 @@ package com.kyant.backdrop.catalog.destinations
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.VectorConverter
-import androidx.compose.foundation.Image
import androidx.compose.foundation.gestures.detectTransformGestures
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
-import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.paint
import androidx.compose.ui.geometry.Offset
@@ -19,15 +16,13 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.TransformOrigin
import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
-import com.kyant.backdrop.backdrop
+import com.kyant.backdrop.catalog.BackdropDemoScaffold
import com.kyant.backdrop.catalog.R
import com.kyant.backdrop.drawBackdrop
import com.kyant.backdrop.effects.refraction
import com.kyant.backdrop.effects.saturation
-import com.kyant.backdrop.rememberBackdrop
import com.kyant.capsule.ContinuousRoundedRectangle
import kotlinx.coroutines.launch
import kotlin.math.PI
@@ -41,29 +36,18 @@ fun GlassPlaygroundContent() {
if (isLightTheme) Color(0xFF0088FF)
else Color(0xFF0091FF)
- val backdrop = rememberBackdrop()
-
val animationScope = rememberCoroutineScope()
val offsetAnimation = remember { Animatable(Offset.Zero, Offset.VectorConverter) }
val zoomAnimation = remember { Animatable(1f) }
val rotationAnimation = remember { Animatable(0f) }
- Box(Modifier.fillMaxSize()) {
- Image(
- painterResource(R.drawable.wallpaper_light),
- null,
- Modifier
- .backdrop(backdrop)
- .fillMaxSize(),
- contentScale = ContentScale.Crop
- )
-
+ BackdropDemoScaffold { backdrop ->
Box(
Modifier
.drawBackdrop(
backdrop,
{ ContinuousRoundedRectangle(48f.dp) },
- layerBlock = {
+ layer = {
val offset = offsetAnimation.value
val zoom = zoomAnimation.value
val rotation = rotationAnimation.value
@@ -107,7 +91,6 @@ fun GlassPlaygroundContent() {
colorFilter = ColorFilter.tint(accentColor)
)
.size(256f.dp)
- .align(Alignment.Center)
)
}
}
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/HomeContent.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/HomeContent.kt
index 0c69eb9..441cf69 100644
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/HomeContent.kt
+++ b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/HomeContent.kt
@@ -1,6 +1,7 @@
package com.kyant.backdrop.catalog.destinations
import androidx.compose.foundation.clickable
+import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.displayCutoutPadding
@@ -9,16 +10,22 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.text.BasicText
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
import com.kyant.backdrop.catalog.CatalogDestination
-import com.kyant.backdrop.catalog.components.Text
-import com.kyant.backdrop.catalog.theme.TextStyles
@Composable
fun HomeContent(onNavigate: (CatalogDestination) -> Unit) {
+ val isLightTheme = !isSystemInDarkTheme()
+ val contentColor = if (isLightTheme) Color.Black else Color.White
+
Column(
Modifier
.verticalScroll(rememberScrollState())
@@ -27,76 +34,55 @@ fun HomeContent(onNavigate: (CatalogDestination) -> Unit) {
.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(16f.dp)
) {
- Text(
+ BasicText(
"Backdrop Catalog",
- TextStyles.headline,
- Modifier.padding(16f.dp, 40f.dp, 16f.dp, 16f.dp)
+ Modifier.padding(16f.dp, 40f.dp, 16f.dp, 16f.dp),
+ style = TextStyle(contentColor, 28f.sp, FontWeight.Medium)
)
+
Column {
- Text(
- "Glass playground",
- TextStyles.body,
- Modifier
- .clickable { onNavigate(CatalogDestination.GlassPlayground) }
- .padding(16f.dp)
- .fillMaxWidth()
- )
- Text(
- "Adaptive luminance glass",
- TextStyles.body,
- Modifier
- .clickable { onNavigate(CatalogDestination.AdaptiveLuminanceGlass) }
- .padding(16f.dp)
- .fillMaxWidth()
- )
- Text(
- "Control center",
- TextStyles.body,
- Modifier
- .clickable { onNavigate(CatalogDestination.ControlCenter) }
- .padding(16f.dp)
- .fillMaxWidth()
- )
- Text(
- "Bottom tabs",
- TextStyles.body,
- Modifier
- .clickable { onNavigate(CatalogDestination.BottomTabs) }
- .padding(16f.dp)
- .fillMaxWidth()
- )
- Text(
- "Icon button",
- TextStyles.body,
- Modifier
- .clickable { onNavigate(CatalogDestination.IconButton) }
- .padding(16f.dp)
- .fillMaxWidth()
- )
- Text(
- "Dialog",
- TextStyles.body,
- Modifier
- .clickable { onNavigate(CatalogDestination.Dialog) }
- .padding(16f.dp)
- .fillMaxWidth()
- )
- Text(
- "Scroll container",
- TextStyles.body,
- Modifier
- .clickable { onNavigate(CatalogDestination.ScrollContainer) }
- .padding(16f.dp)
- .fillMaxWidth()
- )
- Text(
- "Lazy scroll container",
- TextStyles.body,
- Modifier
- .clickable { onNavigate(CatalogDestination.LazyScrollContainer) }
- .padding(16f.dp)
- .fillMaxWidth()
- )
+ Subtitle("Liquid glass components")
+ ListItem({ onNavigate(CatalogDestination.Buttons) }, "Buttons")
+ ListItem({ onNavigate(CatalogDestination.BottomTabs) }, "Bottom tabs")
+ ListItem({ onNavigate(CatalogDestination.Dialog) }, "Dialog")
+
+ Subtitle("System UIs")
+ ListItem({ onNavigate(CatalogDestination.ControlCenter) }, "Control center")
+
+ Subtitle("Experiments")
+ ListItem({ onNavigate(CatalogDestination.GlassPlayground) }, "Glass playground")
+ ListItem({ onNavigate(CatalogDestination.AdaptiveLuminanceGlass) }, "Adaptive luminance glass")
+ ListItem({ onNavigate(CatalogDestination.ScrollContainer) }, "Scroll container")
+ ListItem({ onNavigate(CatalogDestination.LazyScrollContainer) }, "Lazy scroll container")
}
}
}
+
+@Composable
+private fun Subtitle(label: String) {
+ BasicText(
+ label,
+ Modifier
+ .padding(16f.dp, 24f.dp, 16f.dp, 8f.dp)
+ .fillMaxWidth(),
+ style = TextStyle(Color(0xFF0088FF), 15f.sp, FontWeight.Medium)
+ )
+}
+
+@Composable
+private fun ListItem(
+ onClick: () -> Unit,
+ label: String
+) {
+ val isLightTheme = !isSystemInDarkTheme()
+ val contentColor = if (isLightTheme) Color.Black else Color.White
+
+ BasicText(
+ label,
+ Modifier
+ .clickable(onClick = onClick)
+ .padding(16f.dp)
+ .fillMaxWidth(),
+ style = TextStyle(contentColor, 17f.sp)
+ )
+}
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/IconButtonContent.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/IconButtonContent.kt
deleted file mode 100644
index f2420d3..0000000
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/IconButtonContent.kt
+++ /dev/null
@@ -1,163 +0,0 @@
-package com.kyant.backdrop.catalog.destinations
-
-import androidx.compose.animation.core.Animatable
-import androidx.compose.animation.core.VectorConverter
-import androidx.compose.animation.core.spring
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.clickable
-import androidx.compose.foundation.interaction.MutableInteractionSource
-import androidx.compose.foundation.isSystemInDarkTheme
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.shape.CircleShape
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.drawWithContent
-import androidx.compose.ui.draw.paint
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.graphics.BlendMode
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.ColorFilter
-import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.layout.ContentScale
-import androidx.compose.ui.res.painterResource
-import androidx.compose.ui.unit.dp
-import com.kyant.backdrop.backdrop
-import com.kyant.backdrop.catalog.R
-import com.kyant.backdrop.catalog.inspectDragGestures
-import com.kyant.backdrop.drawBackdrop
-import com.kyant.backdrop.effects.blur
-import com.kyant.backdrop.effects.refraction
-import com.kyant.backdrop.effects.saturation
-import com.kyant.backdrop.rememberBackdrop
-import kotlinx.coroutines.launch
-import kotlin.math.abs
-import kotlin.math.atan2
-import kotlin.math.cos
-import kotlin.math.sin
-import kotlin.math.tanh
-
-@Composable
-fun IconButtonContent() {
- val isLightTheme = !isSystemInDarkTheme()
- val accentColor =
- if (isLightTheme) Color(0xFF0088FF)
- else Color(0xFF0091FF)
- val containerColor =
- if (isLightTheme) Color(0xFFFAFAFA).copy(0.4f)
- else Color(0xFF121212).copy(0.4f)
-
- val backdrop = rememberBackdrop()
-
- val animationScope = rememberCoroutineScope()
- val pressAnimation = remember { Animatable(0f) }
- val offsetAnimation = remember { Animatable(Offset.Zero, Offset.VectorConverter) }
- val scaleAnimation = remember { Animatable(0f) }
-
- Box(Modifier.fillMaxSize()) {
- Image(
- painterResource(R.drawable.system_home_screen_light),
- null,
- Modifier
- .backdrop(backdrop)
- .fillMaxSize(),
- contentScale = ContentScale.Crop
- )
-
- Box(
- Modifier
- .drawBackdrop(
- backdrop,
- { CircleShape },
- layerBlock = {
- val offset = offsetAnimation.value
- val scale = 1f + 12f.dp.toPx() / size.minDimension * scaleAnimation.value
- val offsetAngle = atan2(offset.y, offset.x)
- val deltaScale = 4f.dp.toPx() / size.minDimension
- translationX = 12f.dp.toPx() * tanh(0.5f * offset.x / size.width)
- translationY = 12f.dp.toPx() * tanh(0.5f * offset.y / size.height)
- scaleX = scale + deltaScale * abs(cos(offsetAngle) * offset.x / size.width)
- scaleY = scale + deltaScale * abs(sin(offsetAngle) * offset.y / size.height)
- },
- onDrawSurface = { drawRect(containerColor) }
- ) {
- saturation()
- blur(8f.dp.toPx())
- refraction(12f.dp.toPx(), size.minDimension / 2f)
- }
- .drawWithContent {
- drawContent()
- drawRect(
- Color.White.copy(0.3f * pressAnimation.value),
- blendMode = BlendMode.Plus
- )
- }
- .clickable(
- interactionSource = remember { MutableInteractionSource() },
- indication = null
- ) {}
- .pointerInput(animationScope) {
- val onDragStop: () -> Unit = {
- animationScope.launch {
- launch {
- pressAnimation.animateTo(
- 0f,
- spring(1f, 300f)
- )
- }
- launch {
- offsetAnimation.animateTo(
- Offset.Zero,
- spring(1f, 300f)
- )
- }
- launch {
- scaleAnimation.animateTo(
- 0f,
- spring(0.5f, 300f)
- )
- }
- }
- }
-
- inspectDragGestures(
- onDragStart = { down ->
- animationScope.launch {
- launch {
- pressAnimation.animateTo(
- 1f,
- spring(1f, 300f)
- )
- }
- launch {
- offsetAnimation.snapTo(Offset.Zero)
- }
- launch {
- scaleAnimation.animateTo(
- 1f,
- spring(0.5f, 300f)
- )
- }
- }
- },
- onDragEnd = { onDragStop() },
- onDragCancel = onDragStop
- ) { _, dragAmount ->
- animationScope.launch {
- offsetAnimation.snapTo(offsetAnimation.value + dragAmount)
- }
- }
- }
- .paint(
- painterResource(R.drawable.flight_40px),
- colorFilter = ColorFilter.tint(accentColor)
- )
- .size(64f.dp)
- .align(Alignment.Center)
- )
- }
-}
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/LazyScrollContainerContent.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/LazyScrollContainerContent.kt
index f1df237..2f837d1 100644
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/LazyScrollContainerContent.kt
+++ b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/LazyScrollContainerContent.kt
@@ -1,6 +1,5 @@
package com.kyant.backdrop.catalog.destinations
-import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
@@ -15,31 +14,16 @@ import androidx.compose.foundation.layout.windowInsetsTopHeight
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
-import androidx.compose.ui.layout.ContentScale
-import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
-import com.kyant.backdrop.backdrop
-import com.kyant.backdrop.catalog.R
+import com.kyant.backdrop.catalog.BackdropDemoScaffold
import com.kyant.backdrop.drawBackdrop
import com.kyant.backdrop.effects.refraction
import com.kyant.backdrop.effects.saturation
-import com.kyant.backdrop.rememberBackdrop
import com.kyant.capsule.ContinuousRoundedRectangle
@Composable
fun LazyScrollContainerContent() {
- val backdrop = rememberBackdrop()
-
- Box(Modifier.fillMaxSize()) {
- Image(
- painterResource(R.drawable.wallpaper_light),
- null,
- Modifier
- .backdrop(backdrop)
- .fillMaxSize(),
- contentScale = ContentScale.Crop
- )
-
+ BackdropDemoScaffold { backdrop ->
LazyColumn(
Modifier.fillMaxSize(),
contentPadding = PaddingValues(16f.dp),
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ScrollContainerContent.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ScrollContainerContent.kt
index 615e1ef..a4e36bf 100644
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ScrollContainerContent.kt
+++ b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ScrollContainerContent.kt
@@ -1,6 +1,5 @@
package com.kyant.backdrop.catalog.destinations
-import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@@ -14,31 +13,16 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
-import androidx.compose.ui.layout.ContentScale
-import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
-import com.kyant.backdrop.backdrop
-import com.kyant.backdrop.catalog.R
+import com.kyant.backdrop.catalog.BackdropDemoScaffold
import com.kyant.backdrop.drawBackdrop
import com.kyant.backdrop.effects.refraction
import com.kyant.backdrop.effects.saturation
-import com.kyant.backdrop.rememberBackdrop
import com.kyant.capsule.ContinuousRoundedRectangle
@Composable
fun ScrollContainerContent() {
- val backdrop = rememberBackdrop()
-
- Box(Modifier.fillMaxSize()) {
- Image(
- painterResource(R.drawable.wallpaper_light),
- null,
- Modifier
- .backdrop(backdrop)
- .fillMaxSize(),
- contentScale = ContentScale.Crop
- )
-
+ BackdropDemoScaffold { backdrop ->
Column(
Modifier
.verticalScroll(rememberScrollState())
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/theme/ContentColor.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/theme/ContentColor.kt
deleted file mode 100644
index 5417179..0000000
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/theme/ContentColor.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.kyant.backdrop.catalog.theme
-
-import androidx.compose.runtime.ProvidableCompositionLocal
-import androidx.compose.runtime.staticCompositionLocalOf
-import androidx.compose.ui.graphics.Color
-
-val LocalContentColor: ProvidableCompositionLocal =
- staticCompositionLocalOf { Color.Black }
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/theme/TextStyles.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/theme/TextStyles.kt
deleted file mode 100644
index e951483..0000000
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/theme/TextStyles.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.kyant.backdrop.catalog.theme
-
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.unit.sp
-
-object TextStyles {
-
- val body: TextStyle = TextStyle(fontSize = 16f.sp)
-
- val headline: TextStyle = TextStyle(fontSize = 28f.sp, fontWeight = FontWeight.Medium)
-}
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/DragGestureInspector.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/utils/DragGestureInspector.kt
similarity index 98%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/DragGestureInspector.kt
rename to catalog/src/main/java/com/kyant/backdrop/catalog/utils/DragGestureInspector.kt
index 4fed13e..d3ae410 100644
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/DragGestureInspector.kt
+++ b/catalog/src/main/java/com/kyant/backdrop/catalog/utils/DragGestureInspector.kt
@@ -1,4 +1,4 @@
-package com.kyant.backdrop.catalog
+package com.kyant.backdrop.catalog.utils
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/ProgressConverter.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/utils/ProgressConverter.kt
similarity index 89%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/ProgressConverter.kt
rename to catalog/src/main/java/com/kyant/backdrop/catalog/utils/ProgressConverter.kt
index 940d52f..f485233 100644
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/ProgressConverter.kt
+++ b/catalog/src/main/java/com/kyant/backdrop/catalog/utils/ProgressConverter.kt
@@ -1,4 +1,4 @@
-package com.kyant.backdrop.catalog
+package com.kyant.backdrop.catalog.utils
import kotlin.math.abs
import kotlin.math.exp
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/UISensor.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/utils/UISensor.kt
similarity index 98%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/UISensor.kt
rename to catalog/src/main/java/com/kyant/backdrop/catalog/utils/UISensor.kt
index c8c89a0..78afb4f 100644
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/UISensor.kt
+++ b/catalog/src/main/java/com/kyant/backdrop/catalog/utils/UISensor.kt
@@ -1,4 +1,4 @@
-package com.kyant.backdrop.catalog
+package com.kyant.backdrop.catalog.utils
import android.content.Context
import android.hardware.Sensor
diff --git a/liquid-glass/src/main/java/com/kyant/liquidglass/Deprecated.kt b/liquid-glass/src/main/java/com/kyant/liquidglass/Deprecated.kt
index d90e9cc..a7e3bb5 100644
--- a/liquid-glass/src/main/java/com/kyant/liquidglass/Deprecated.kt
+++ b/liquid-glass/src/main/java/com/kyant/liquidglass/Deprecated.kt
@@ -48,7 +48,7 @@ fun Modifier.liquidGlass(
this
.drawBackdrop(
backdrop = backdrop,
- shapeProvider = { style().shape },
+ shape = { style().shape },
highlight = {
style().highlight?.let {
Highlight(