diff --git a/app/src/main/java/dev/baseio/composeplayground/MainActivity.kt b/app/src/main/java/dev/baseio/composeplayground/MainActivity.kt
index 1b20171..e318d65 100644
--- a/app/src/main/java/dev/baseio/composeplayground/MainActivity.kt
+++ b/app/src/main/java/dev/baseio/composeplayground/MainActivity.kt
@@ -23,6 +23,7 @@ import com.google.accompanist.pager.rememberPagerState
import dev.baseio.composeplayground.ui.animations.*
import dev.baseio.composeplayground.ui.animations.planetarysystem.PlanetarySystem
import dev.baseio.composeplayground.ui.animations.pulltorefresh.PullToRefreshOne
+import dev.baseio.composeplayground.ui.animations.springwave.SpringWaveAnimation
import dev.baseio.composeplayground.ui.theme.ComposePlaygroundTheme
class MainActivity : ComponentActivity() {
@@ -54,7 +55,7 @@ class MainActivity : ComponentActivity() {
modifier = Modifier
.weight(1f)
.fillMaxWidth(),
- count = 10, state = pagerState,
+ count = 11, state = pagerState,
) { page ->
// Our page content
when (page) {
@@ -106,6 +107,9 @@ class MainActivity : ComponentActivity() {
BellAnimation(Modifier.align(Alignment.Center))
}
}
+ 10 -> {
+ SpringWaveAnimation()
+ }
}
}
HorizontalPagerIndicator(
diff --git a/app/src/main/java/dev/baseio/composeplayground/contributors/PrateekSharma.kt b/app/src/main/java/dev/baseio/composeplayground/contributors/PrateekSharma.kt
new file mode 100644
index 0000000..467569a
--- /dev/null
+++ b/app/src/main/java/dev/baseio/composeplayground/contributors/PrateekSharma.kt
@@ -0,0 +1,31 @@
+package dev.baseio.composeplayground.contributors
+
+import androidx.compose.foundation.layout.*
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import dev.baseio.composeplayground.R
+import dev.baseio.composeplayground.ui.theme.Typography
+
+const val prateekImageUrl = "https://pbs.twimg.com/profile_images/1496554615688425472/M6rm_jwG_normal.jpg"
+
+@Composable
+fun PrateekSharma(modifier: Modifier = Modifier) {
+ Row(verticalAlignment = Alignment.CenterVertically, modifier = modifier.padding(4.dp)) {
+ CoilImageBox(Modifier.size(64.dp), prateekImageUrl)
+ Column(verticalArrangement = Arrangement.Center, modifier = Modifier.padding(8.dp)) {
+ Text(
+ text = stringResource(id = R.string.prateek),
+ style = Typography.h6.copy(MaterialTheme.colors.onSurface),
+ )
+ Text(
+ text = stringResource(id = R.string.prateek_email),
+ style = Typography.subtitle1.copy(MaterialTheme.colors.onSurface),
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/dev/baseio/composeplayground/ui/animations/springwave/Oval3D.kt b/app/src/main/java/dev/baseio/composeplayground/ui/animations/springwave/Oval3D.kt
new file mode 100644
index 0000000..7b88651
--- /dev/null
+++ b/app/src/main/java/dev/baseio/composeplayground/ui/animations/springwave/Oval3D.kt
@@ -0,0 +1,63 @@
+package dev.baseio.composeplayground.ui.animations.springwave
+
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.width
+import androidx.compose.material.Surface
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Rect
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.graphics.*
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.unit.dp
+
+
+/*
+* Give [ Width = 3 * Height ] to see better view of the oval in 3D
+* */
+@Composable
+fun Oval3D(
+ givenSurfaceWidth: Float,
+ givenSurfaceHeight: Float,
+ modifier: Modifier
+) {
+ Surface(modifier = modifier
+ .width(givenSurfaceWidth.dp)
+ .height(givenSurfaceHeight.dp),
+ color = Color.White,
+ shape = object : Shape {
+ override fun createOutline(
+ size: Size,
+ layoutDirection: LayoutDirection,
+ density: Density
+ ): Outline {
+ val thickness = 14f
+ val p1 = Path().apply {
+ addOval(Rect(0f, 0f, size.width, size.height))
+ }
+ val p2 = Path().apply {
+ addOval(
+ Rect(
+ thickness + 5,
+ thickness - 9,
+ size.width - thickness - 5,
+ size.height - thickness - 3
+ )
+ )
+ }
+ val p3 = Path()
+ p3.op(p1, p2, PathOperation.Difference)
+ return Outline.Generic(p3)
+ }
+ }
+ ) {
+ }
+}
+
+@Composable
+@Preview
+fun Oval3DPrev() {
+ Oval3D(givenSurfaceWidth = 99f, givenSurfaceHeight = 33f, Modifier)
+}
\ No newline at end of file
diff --git a/app/src/main/java/dev/baseio/composeplayground/ui/animations/springwave/SpringWaveAnimation.kt b/app/src/main/java/dev/baseio/composeplayground/ui/animations/springwave/SpringWaveAnimation.kt
new file mode 100644
index 0000000..202a6e9
--- /dev/null
+++ b/app/src/main/java/dev/baseio/composeplayground/ui/animations/springwave/SpringWaveAnimation.kt
@@ -0,0 +1,161 @@
+package dev.baseio.composeplayground.ui.animations.springwave
+
+import androidx.compose.animation.core.*
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.*
+import androidx.compose.material.Button
+import androidx.compose.material.Text
+import androidx.compose.runtime.*
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.*
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import dev.baseio.composeplayground.contributors.PrateekSharma
+import dev.baseio.composeplayground.ui.animations.springwave.AnimationState.End
+import dev.baseio.composeplayground.ui.animations.springwave.AnimationState.Start
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+@Composable
+fun SpringWaveAnimation() {
+ val smallestWidth = 27f
+ val smallestHeight = 9f
+
+ var currentAnimationState by remember { mutableStateOf(Start)}
+
+ val circle1offsetState = remember {
+ Animatable(if(currentAnimationState==Start) 500f else 200f)
+ }
+
+ val circle2offsetState = remember {
+ Animatable(if(currentAnimationState==Start) 497.5f else 197.5f)
+ }
+
+ val circle3offsetState = remember {
+ Animatable(if(currentAnimationState==Start) 495f else 195f)
+ }
+
+ val circle4offsetState = remember {
+ Animatable(if(currentAnimationState==Start) 492.5f else 192.5f)
+ }
+
+ val circle5offsetState = remember {
+ Animatable(if(currentAnimationState==Start) 489.75f else 189.75f)
+ }
+
+ val circle6offsetState = remember {
+ Animatable(if(currentAnimationState==Start) 487f else 187f)
+ }
+
+ val circle7offsetState = remember {
+ Animatable(if(currentAnimationState==Start) 484f else 184f)
+ }
+
+ LaunchedEffect(key1 = currentAnimationState) {
+ launch {
+ /*
+ * Need to launch these coroutines in different different
+ * scopes because we want that they all run simultaneously
+ * with there own delays from the global starting time.
+ *
+ * If we would have used these all animateTo() methods in
+ * a single coroutine scope then they would run sequentially
+ * one after another; means that the second ring would start moving
+ * only after the damping effect of the first ring completes.
+ * */
+
+ launch {
+ circle1offsetState.animateTo(
+ if(currentAnimationState==Start) 200f else 500f,
+ spring(Spring.DampingRatioHighBouncy, Spring.StiffnessVeryLow))
+ }
+ launch {
+ delay(40)
+ circle2offsetState.animateTo(
+ if(currentAnimationState==Start) 197.5f else 497.5f,
+ spring(Spring.DampingRatioHighBouncy, Spring.StiffnessVeryLow))
+ }
+ launch {
+ delay(90)
+ circle3offsetState.animateTo(
+ if(currentAnimationState==Start) 195f else 495f,
+ spring(Spring.DampingRatioHighBouncy, Spring.StiffnessVeryLow))
+ }
+ launch {
+ delay(130)
+ circle4offsetState.animateTo(
+ if(currentAnimationState==Start) 192.5f else 492.5f,
+ spring(Spring.DampingRatioHighBouncy, Spring.StiffnessVeryLow))
+ }
+ launch {
+ delay(170)
+ circle5offsetState.animateTo(
+ if(currentAnimationState==Start) 189.75f else 489.75f,
+ spring(Spring.DampingRatioHighBouncy, Spring.StiffnessVeryLow))
+ }
+ launch {
+ delay(210)
+ circle6offsetState.animateTo(
+ if(currentAnimationState==Start) 187f else 487f,
+ spring(Spring.DampingRatioHighBouncy, Spring.StiffnessVeryLow))
+ }
+ launch {
+ delay(250)
+ circle7offsetState.animateTo(
+ if(currentAnimationState==Start) 184f else 484f,
+ spring(Spring.DampingRatioHighBouncy, Spring.StiffnessVeryLow)
+ )
+ }
+ }
+ }
+
+ BoxWithConstraints(
+ modifier = Modifier
+ .background(Color.Black)
+ .fillMaxSize()
+ ) {
+ Oval3D(givenSurfaceWidth = smallestWidth, givenSurfaceHeight = smallestHeight, modifier = Modifier.absoluteOffset(this.maxWidth/2, circle1offsetState.value.dp))
+ Oval3D(givenSurfaceWidth = smallestWidth*2, givenSurfaceHeight = smallestHeight*2.1f, modifier = Modifier.absoluteOffset(this.maxWidth/2-(13).dp, circle2offsetState.value.dp))
+ Oval3D(givenSurfaceWidth = smallestWidth*3, givenSurfaceHeight = smallestHeight*3.2f, modifier = Modifier.absoluteOffset(this.maxWidth/2-(26.5).dp, circle3offsetState.value.dp))
+ Oval3D(givenSurfaceWidth = smallestWidth*4, givenSurfaceHeight = smallestHeight*4.4f, modifier = Modifier.absoluteOffset(this.maxWidth/2-40.dp, circle4offsetState.value.dp))
+ Oval3D(givenSurfaceWidth = smallestWidth*5, givenSurfaceHeight = smallestHeight*5.6f, modifier = Modifier.absoluteOffset(this.maxWidth/2-53.dp, circle5offsetState.value.dp))
+ Oval3D(givenSurfaceWidth = smallestWidth*6, givenSurfaceHeight = smallestHeight*6.9f, modifier = Modifier.absoluteOffset(this.maxWidth/2-(67).dp, circle6offsetState.value.dp))
+ Oval3D(givenSurfaceWidth = smallestWidth*7, givenSurfaceHeight = smallestHeight*8.2f, modifier = Modifier.absoluteOffset(this.maxWidth/2-(80).dp, circle7offsetState.value.dp))
+
+ PrateekSharma(
+ Modifier.background(Color.White).absoluteOffset(y=5.dp)
+ )
+
+ Button(
+ modifier = Modifier
+ .align(Alignment.BottomCenter)
+ .wrapContentSize(align = Alignment.Center),
+ onClick = {
+ if(currentAnimationState == End) {
+ currentAnimationState = Start
+ } else {
+ currentAnimationState = End
+ }
+ }) {
+ Text(
+ text = if(currentAnimationState==Start) {
+ "Move the wave to down"
+ } else {
+ "Move the wave to Up"
+ }
+ )
+ }
+ }
+}
+
+enum class AnimationState {
+ Start, End
+}
+
+
+@Preview(showBackground = true, showSystemUi = true)
+@Composable
+fun SpringWaveAnimPrev() {
+ SpringWaveAnimation()
+}
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index a144b92..c61403d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -2,6 +2,8 @@
Compose Playground
Anmol Verma
anmol.verma@mutualmobile.com\nanmol.verma4@gmail.com
+ Prateek Sharma
+ sharmaprateek196@gmail.com
LOADING
\ No newline at end of file