Skip to content

Commit

Permalink
Merge pull request #1 from Adityapanther/extend-functionality
Browse files Browse the repository at this point in the history
added dismiss method with animation & orientation direction added
  • Loading branch information
Adityapanther authored Mar 2, 2024
2 parents 2cf7f1d + c1377d8 commit 10df658
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 58 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:8.1.4")
classpath("com.android.tools.build:gradle:8.3.0")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0")
}
}
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Fri Aug 18 16:00:36 CDT 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
4 changes: 2 additions & 2 deletions sample/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ android {
defaultConfig {
applicationId = "moe.tlaster.swiper"
minSdk = 21
targetSdk = 33
targetSdk = 34
versionCode = 1
versionName = "1.0"

Expand Down Expand Up @@ -59,7 +59,7 @@ dependencies {
implementation("androidx.compose.ui:ui-tooling:${rootProject.extra["compose_version"]}")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
implementation("androidx.activity:activity-compose:1.8.2")
testImplementation("junit:junit:4.+")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
androidTestImplementation("androidx.compose.ui:ui-test-junit4:${rootProject.extra["compose_version"]}")
Expand Down
115 changes: 78 additions & 37 deletions sample/src/main/java/moe/tlaster/swiper/sample/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,30 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.layout.*
import androidx.compose.material.Button
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
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.draw.alpha
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import moe.tlaster.swiper.Direction
import moe.tlaster.swiper.Swiper
import moe.tlaster.swiper.rememberSwiperState

Expand All @@ -27,43 +37,74 @@ class MainActivity : ComponentActivity() {
setContent {
MaterialTheme {
Scaffold {
var show by remember {
mutableStateOf(false)
}
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
Button(onClick = { show = true }) {
Text(text = "ClickMe")
}
Text(text = "show: $show")
}
if (show) {
val state = rememberSwiperState(
onDismiss = {
show = false
}
)
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.Black.copy(alpha = 1 - state.progress))
.alpha(1 - state.progress),
) {
Swiper(
state = state,
) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(400.dp)
.background(Color.Red)
)
}
}
}
Surface (
modifier = Modifier.padding(it)
){
var show by remember { mutableStateOf(false) }
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
Button(onClick = { show = true }) {
Text(text = "ClickMe")
}
Text(text = "show: $show")
}
if (show) {
val state = rememberSwiperState(
onDismiss = {
show = false
}
)
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.Black.copy(alpha = 1 - state.progress))
.alpha(1 - state.progress),
) {
Swiper(
state = state,
orientation = Orientation.Horizontal,
direction = Direction.Left
) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(400.dp)
.background(Color.Gray)
){
Column (
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Bottom,
horizontalAlignment = Alignment.CenterHorizontally
){
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
val scope = rememberCoroutineScope()
IconButton(
onClick = {
scope.launch(Dispatchers.Default){
state.dismissIt()
}
}) {
Icon(
imageVector = Icons.Default.Close,
contentDescription = "Close it",
tint = Color.White
)
}
}
}
}
}
}
}
}

}
}
}
Expand Down
6 changes: 3 additions & 3 deletions swiper/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ plugins {
android {
namespace = "moe.tlaster.swiper"

compileSdk = 33
compileSdk = 34

defaultConfig {
minSdk = 21
Expand All @@ -34,7 +34,7 @@ dependencies {
androidTestImplementation(composeBom)

implementation("androidx.compose.foundation:foundation")
testImplementation("junit:junit:4.+")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
}
Expand All @@ -45,7 +45,7 @@ afterEvaluate {
create<MavenPublication>("release") {
groupId = "moe.tlaster"
artifactId = "swiper"
version = "0.7.3"
version = "0.8.0"

from(components["release"])
}
Expand Down
9 changes: 9 additions & 0 deletions swiper/src/main/java/moe/tlaster/swiper/Direction.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package moe.tlaster.swiper

enum class Direction {
Left,
Right,
Up,
Down
}

6 changes: 6 additions & 0 deletions swiper/src/main/java/moe/tlaster/swiper/DismissHeight.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package moe.tlaster.swiper

object DismissHeight {
const val HALF = 0.5f
}

10 changes: 8 additions & 2 deletions swiper/src/main/java/moe/tlaster/swiper/Swiper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ fun Swiper(
orientation: Orientation = Orientation.Vertical,
enabled: Boolean = true,
reverseDirection: Boolean = false,
direction: Direction = Direction.Up,
dismissHeight: Float = DismissHeight.HALF,
animDurationMillis: Int = 500,
content: @Composable () -> Unit,
) {
val scope = rememberCoroutineScope()
Expand All @@ -27,6 +30,9 @@ fun Swiper(
) {
LaunchedEffect(constraints.maxHeight) {
state.maxHeight = constraints.maxHeight
state.direction = direction
state.dismissHeight = dismissHeight
state.animDuration = animDurationMillis
}
Layout(
modifier = Modifier.draggable(
Expand All @@ -50,11 +56,11 @@ fun Swiper(
},
),
content = content,
) { measurables, constraints ->
) { measureScope, constraints ->
layout(constraints.maxWidth, constraints.maxHeight) {
val offset = state.offset
val childConstraints = constraints.copy(minWidth = 0, minHeight = 0)
measurables
measureScope
.map {
it.measure(childConstraints)
}
Expand Down
81 changes: 69 additions & 12 deletions swiper/src/main/java/moe/tlaster/swiper/SwiperState.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package moe.tlaster.swiper

import androidx.compose.animation.core.Animatable
import androidx.compose.runtime.*
import androidx.compose.animation.core.tween
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.Saver
import androidx.compose.runtime.saveable.listSaver
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import kotlin.math.abs
import kotlin.math.absoluteValue
import kotlin.math.withSign

Expand Down Expand Up @@ -41,6 +47,9 @@ class SwiperState(
}
internal var dismissed by mutableStateOf(false)
private var _offset = Animatable(initialOffset)
private lateinit var _direction: Direction
private var _dismissHeight: Float = 0f
private var _animDuration: Int = 0

val offset: Float
get() = _offset.value
Expand All @@ -55,18 +64,47 @@ class SwiperState(
_offset.snapTo(value)
}

internal var direction: Direction = Direction.Up
set(value) {
_direction = value
field = value
}

internal var dismissHeight: Float = 0f
set(value) {
_dismissHeight = value
field = value
}

internal var animDuration: Int = 0
set(value) {
_animDuration = value
field = value
}

internal suspend fun fling(velocity: Float) {
val value = _offset.value
when {
velocity.absoluteValue > 4000f -> {
dismiss(velocity)
}
value.absoluteValue < maxHeight * 0.5 -> {
restore()
}
value.absoluteValue < maxHeight -> {
dismiss(velocity)
val calcCurrentHeight = abs(value) / 1000
if(velocity.absoluteValue == 0.0f && calcCurrentHeight > dismissHeight){
when {
_direction == Direction.Up && value < 0.0 -> {
dismiss(velocity)
}
_direction == Direction.Down && value > 0.0 -> {
dismiss(velocity)
}
_direction == Direction.Left && value < 0.0 -> {
dismiss(velocity)
}
_direction == Direction.Right && value > 0.0 -> {
dismiss(velocity)
}
else -> {
restore()
}
}
}else {
restore()
}
}

Expand All @@ -83,6 +121,24 @@ class SwiperState(
dismissed = false
}

private suspend fun clickToDismiss(){
dismissed = true
when (_direction) {
Direction.Right, Direction.Up -> {
_offset.animateTo(( - maxHeight.toFloat()), initialVelocity = 0.0f, animationSpec = tween(_animDuration))
onDismiss.invoke()
}
Direction.Left, Direction.Down -> {
_offset.animateTo(maxHeight.toFloat(), initialVelocity = 0.0f, animationSpec = tween(_animDuration))
onDismiss.invoke()
}
}
restore()
}
suspend fun dismissIt(){
clickToDismiss()
}

companion object {
fun Saver(
onStart: () -> Unit = {},
Expand All @@ -99,9 +155,10 @@ class SwiperState(
onStart = onStart,
onDismiss = onDismiss,
onEnd = onEnd,
initialOffset = it[0],
initialOffset = it[0]
)
}
)
}
}
}

0 comments on commit 10df658

Please sign in to comment.