Skip to content

Commit e23aa85

Browse files
committed
changes: add slide animation with controller
1 parent 79f76d5 commit e23aa85

File tree

15 files changed

+860
-14
lines changed

15 files changed

+860
-14
lines changed

.idea/inspectionProfiles/Project_Default.xml

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/build.gradle.kts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ android {
5252
}
5353

5454
dependencies {
55+
implementation(libs.commonmodule)
5556
implementation(libs.cascade)
5657
implementation(libs.cascade.compose)
5758
implementation(libs.lottie)
@@ -65,15 +66,11 @@ dependencies {
6566
implementation(libs.compose.material)
6667
implementation(libs.compose.material3)
6768
implementation(libs.navigation.compose)
68-
// implementation(libs.coil.kt)
69+
implementation(libs.coil.kt)
6970
implementation(libs.coil.kt.compose)
7071
testImplementation(libs.junit)
7172
androidTestImplementation(libs.androidx.test.ext.junit)
7273
androidTestImplementation(libs.espresso.core)
73-
// migrate deprecated deps
74-
// implementation("com.google.accompanist:accompanist-navigation-animation:0.29.1-alpha")
75-
implementation(libs.commonmodule)
76-
implementation("com.google.accompanist:accompanist-systemuicontroller:0.29.1-alpha")
7774
androidTestImplementation(platform(libs.compose.bom))
7875
androidTestImplementation(libs.android.test.compose.ui.test.junit4)
7976
debugImplementation(libs.compose.ui.tooling)

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
xmlns:tools="http://schemas.android.com/tools">
44

55
<uses-permission android:name="android.permission.INTERNET" />
6+
<uses-permission android:name="android.permission.VIBRATE" />
67

78
<application
89
android:allowBackup="true"
910
android:dataExtractionRules="@xml/data_extraction_rules"
1011
android:enableOnBackInvokedCallback="true"
11-
1212
android:fullBackupContent="@xml/backup_rules"
1313
android:icon="@mipmap/ic_launcher"
1414
android:label="@string/app_name"
@@ -21,10 +21,8 @@
2121
android:theme="@style/Theme.Animations">
2222
<intent-filter>
2323
<action android:name="android.intent.action.MAIN" />
24-
2524
<category android:name="android.intent.category.LAUNCHER" />
2625
</intent-filter>
2726
</activity>
2827
</application>
29-
3028
</manifest>

app/src/main/java/pro/jayeshseth/animations/navigation/NavGraph.kt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ import pro.jayeshseth.animations.ui.screens.AnimatedTransition
1010
import pro.jayeshseth.animations.ui.screens.BouncyRope
1111
import pro.jayeshseth.animations.ui.screens.HomeScreen
1212
import pro.jayeshseth.animations.ui.screens.InfiniteRotation
13+
import pro.jayeshseth.animations.ui.screens.ItemPlacementAnimation
14+
import pro.jayeshseth.animations.ui.screens.SlideItemPlacement
1315
import pro.jayeshseth.animations.ui.screens.SwipeRefresh
16+
import pro.jayeshseth.animations.ui.screens.TrippyBlinders
1417
import pro.jayeshseth.animations.ui.screens.VisibilityAnimation
1518

1619
@Composable
@@ -29,7 +32,8 @@ fun NavGraph() {
2932
navToAnimateInfiniteRotation = { navController.navigate("INFINITE_ROTATION") },
3033
navToSwipeRefresh = { navController.navigate("SWIPE_REFRESH") },
3134
navToBouncyRopes = { navController.navigate("BOUNCY_ROPE") },
32-
navToAnimateValueAsState = { navController.navigate("ANIMATE_VALUE_AS_STATE") }
35+
navToAnimateValueAsState = { navController.navigate("ANIMATE_VALUE_AS_STATE") },
36+
navToAnimatedListItemPlacement = { navController.navigate("ITEM_PLACEMENT_ANIMATION") }
3337
)
3438
}
3539
composable("ANIMATE_VISIBILITY") {
@@ -56,5 +60,17 @@ fun NavGraph() {
5660
composable("ANIMATE_VALUE_AS_STATE") {
5761
AnimateValueAsState()
5862
}
63+
composable("SLIDE_IN_OUT") {
64+
SlideItemPlacement()
65+
}
66+
composable("ITEM_PLACEMENT_ANIMATION") {
67+
ItemPlacementAnimation(
68+
navToTrippyBlinders = { navController.navigate("TRIPPY_BLINDER") },
69+
navToSlideInOut = { navController.navigate("SLIDE_IN_OUT") }
70+
)
71+
}
72+
composable("TRIPPY_BLINDER") {
73+
TrippyBlinders()
74+
}
5975
}
6076
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package pro.jayeshseth.animations.ui.composables
2+
3+
import androidx.compose.foundation.layout.Arrangement
4+
import androidx.compose.foundation.layout.Column
5+
import androidx.compose.foundation.layout.Row
6+
import androidx.compose.foundation.layout.fillMaxWidth
7+
import androidx.compose.runtime.Composable
8+
import androidx.compose.ui.Alignment
9+
import androidx.compose.ui.Modifier
10+
import androidx.compose.ui.unit.dp
11+
12+
@Composable
13+
fun ControllerTemplate(
14+
title: @Composable () -> Unit,
15+
content: @Composable () -> Unit,
16+
modifier: Modifier = Modifier
17+
) {
18+
Column(
19+
modifier = modifier,
20+
verticalArrangement = Arrangement.spacedBy(8.dp)
21+
) {
22+
Row(
23+
horizontalArrangement = Arrangement.SpaceBetween,
24+
verticalAlignment = Alignment.CenterVertically,
25+
modifier = Modifier
26+
.fillMaxWidth()
27+
) {
28+
title()
29+
}
30+
content()
31+
}
32+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package pro.jayeshseth.animations.ui.composables
2+
3+
import androidx.compose.foundation.layout.ColumnScope
4+
import androidx.compose.foundation.layout.fillMaxWidth
5+
import androidx.compose.foundation.shape.RoundedCornerShape
6+
import androidx.compose.material3.ExperimentalMaterial3Api
7+
import androidx.compose.material3.ExposedDropdownMenuBox
8+
import androidx.compose.material3.ExposedDropdownMenuDefaults
9+
import androidx.compose.material3.MenuAnchorType
10+
import androidx.compose.material3.TextField
11+
import androidx.compose.runtime.Composable
12+
import androidx.compose.ui.Modifier
13+
import androidx.compose.ui.graphics.Color
14+
import androidx.compose.ui.unit.dp
15+
16+
@OptIn(ExperimentalMaterial3Api::class)
17+
@Composable
18+
fun DropDownTemplate(
19+
value: String,
20+
expanded: Boolean,
21+
onExpandedChange: (Boolean) -> Unit,
22+
title: @Composable () -> Unit,
23+
onDismissRequest: () -> Unit,
24+
content: @Composable ColumnScope.() -> Unit,
25+
modifier: Modifier = Modifier
26+
) {
27+
ControllerTemplate(
28+
modifier = modifier,
29+
title = title,
30+
content = {
31+
ExposedDropdownMenuBox(
32+
expanded = expanded,
33+
onExpandedChange = onExpandedChange,
34+
) {
35+
TextField(
36+
modifier = Modifier
37+
.fillMaxWidth()
38+
.menuAnchor(MenuAnchorType.PrimaryNotEditable),
39+
value = value,
40+
onValueChange = {},
41+
readOnly = true,
42+
singleLine = true,
43+
shape = RoundedCornerShape(50.dp),
44+
trailingIcon = {
45+
ExposedDropdownMenuDefaults.TrailingIcon(
46+
expanded = expanded
47+
)
48+
},
49+
colors = ExposedDropdownMenuDefaults.textFieldColors(
50+
focusedIndicatorColor = Color.Transparent,
51+
unfocusedIndicatorColor = Color.Transparent,
52+
disabledIndicatorColor = Color.Transparent,
53+
),
54+
)
55+
ExposedDropdownMenu(
56+
expanded = expanded,
57+
onDismissRequest = onDismissRequest,
58+
shape = RoundedCornerShape(25.dp),
59+
content = content,
60+
)
61+
}
62+
}
63+
)
64+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package pro.jayeshseth.animations.ui.composables
2+
3+
import androidx.compose.foundation.layout.Arrangement
4+
import androidx.compose.foundation.layout.Row
5+
import androidx.compose.foundation.layout.fillMaxWidth
6+
import androidx.compose.foundation.layout.height
7+
import androidx.compose.foundation.layout.padding
8+
import androidx.compose.material3.LocalContentColor
9+
import androidx.compose.material3.MaterialTheme
10+
import androidx.compose.material3.Slider
11+
import androidx.compose.material3.Text
12+
import androidx.compose.runtime.Composable
13+
import androidx.compose.runtime.CompositionLocalProvider
14+
import androidx.compose.runtime.mutableFloatStateOf
15+
import androidx.compose.runtime.remember
16+
import androidx.compose.runtime.rememberUpdatedState
17+
import androidx.compose.ui.Alignment
18+
import androidx.compose.ui.Modifier
19+
import androidx.compose.ui.tooling.preview.Preview
20+
import androidx.compose.ui.unit.dp
21+
import kotlin.math.roundToInt
22+
23+
@Composable
24+
fun SliderTemplate(
25+
title: String,
26+
value: Float,
27+
step: Float,
28+
onValueChange: (Float) -> Unit,
29+
valueRange: ClosedFloatingPointRange<Float>
30+
) {
31+
val sliderValue = rememberUpdatedState(value)
32+
ControllerTemplate(
33+
title = {
34+
Row(
35+
horizontalArrangement = Arrangement.SpaceBetween,
36+
verticalAlignment = Alignment.CenterVertically,
37+
modifier = Modifier
38+
.fillMaxWidth()
39+
) {
40+
Text(
41+
text = title,
42+
color = MaterialTheme.colorScheme.onBackground,
43+
)
44+
CompositionLocalProvider(
45+
LocalContentColor provides MaterialTheme.colorScheme.onBackground,
46+
) {
47+
val snappedValue = snapSliderValue(valueRange.start, sliderValue.value, step)
48+
Text(
49+
text = "${snappedValue.roundToInt()}",
50+
color = MaterialTheme.colorScheme.onSurfaceVariant,
51+
)
52+
}
53+
}
54+
},
55+
content = {
56+
Slider(
57+
value = sliderValue.value,
58+
onValueChange = onValueChange,
59+
onValueChangeFinished = { },
60+
valueRange = valueRange,
61+
steps = getSteps(valueRange, step),
62+
modifier = Modifier
63+
.padding(top = 2.dp, bottom = 12.dp)
64+
.height(24.dp),
65+
)
66+
}
67+
)
68+
}
69+
70+
private fun getSteps(valueRange: ClosedFloatingPointRange<Float>, step: Float): Int {
71+
if (step == 0f) return 0
72+
val start = valueRange.start
73+
val end = valueRange.endInclusive
74+
val steps = ((end - start) / step).toInt()
75+
require(start + step * steps == end) {
76+
"value range must be a multiple of step"
77+
}
78+
return steps - 1
79+
}
80+
81+
private fun snapSliderValue(start: Float, value: Float, step: Float): Float {
82+
if (step == 0f) return value
83+
val distance = value - start
84+
val stepsFromStart = (distance / step).roundToInt()
85+
val snappedDistance = stepsFromStart * step
86+
return start + snappedDistance
87+
}
88+
89+
@Preview(showBackground = true)
90+
@Composable
91+
private fun Preview() {
92+
val value = remember {
93+
mutableFloatStateOf(0f)
94+
}
95+
SliderTemplate(
96+
title = "title",
97+
value = value.floatValue,
98+
step = 0.1f,
99+
onValueChange = {
100+
value.floatValue = it
101+
},
102+
valueRange = 0f..100f
103+
)
104+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package pro.jayeshseth.animations.ui.composables
2+
3+
import androidx.compose.foundation.layout.Arrangement
4+
import androidx.compose.foundation.layout.Row
5+
import androidx.compose.foundation.layout.Spacer
6+
import androidx.compose.foundation.layout.padding
7+
import androidx.compose.material3.Switch
8+
import androidx.compose.material3.Text
9+
import androidx.compose.runtime.Composable
10+
import androidx.compose.ui.Alignment
11+
import androidx.compose.ui.Modifier
12+
import androidx.compose.ui.unit.dp
13+
14+
@Composable
15+
fun Toggler(
16+
title: String,
17+
checked: Boolean,
18+
onCheckedChanged: (Boolean) -> Unit,
19+
modifier: Modifier = Modifier,
20+
enabled: Boolean = true
21+
) {
22+
Row(
23+
modifier = modifier,
24+
horizontalArrangement = Arrangement.SpaceBetween,
25+
verticalAlignment = Alignment.CenterVertically
26+
) {
27+
Text(text = title)
28+
Spacer(modifier = Modifier.padding(8.dp))
29+
Switch(
30+
checked = checked,
31+
onCheckedChange = onCheckedChanged,
32+
enabled = enabled
33+
)
34+
}
35+
}

app/src/main/java/pro/jayeshseth/animations/ui/screens/HomeScreen.kt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,17 @@ fun HomeScreen(
2626
navToAnimateInfiniteRotation: () -> Unit,
2727
navToSwipeRefresh: () -> Unit,
2828
navToBouncyRopes: () -> Unit,
29-
navToAnimateValueAsState: () -> Unit
29+
navToAnimateValueAsState: () -> Unit,
30+
navToAnimatedListItemPlacement: () -> Unit
3031
) {
3132
val scrollState = rememberScrollState()
3233
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState())
3334
HomeScaffold(
34-
innerScrollState = scrollState,
35+
verticalScrollState = scrollState,
3536
topAppBarScrollBehavior = scrollBehavior,
3637
title = {
3738
Text(
38-
text = "Animations in Jetpack Compose",
39+
text = "Animations",
3940
fontSize = 25.sp,
4041
fontWeight = FontWeight.Bold
4142
)
@@ -51,6 +52,10 @@ fun HomeScreen(
5152
text = "Animate Visibility",
5253
onClick = navToAnimateVisibility,
5354
)
55+
InteractiveButton(
56+
text = "Animated List Item Placement",
57+
onClick = navToAnimatedListItemPlacement,
58+
)
5459
InteractiveButton(
5560
text = "Animated Content",
5661
onClick = navToAnimateContent,
@@ -79,6 +84,10 @@ fun HomeScreen(
7984
text = "Bouncy Ropes",
8085
onClick = navToBouncyRopes
8186
)
87+
InteractiveButton(
88+
text = "About",
89+
onClick = navToBouncyRopes
90+
)
8291
}
8392
}
8493
}

0 commit comments

Comments
 (0)