diff --git a/README.md b/README.md index 94f485c..ef3fc18 100644 --- a/README.md +++ b/README.md @@ -37,34 +37,18 @@ ```gradle // 极致体验的Compose刷新组件 (*必须) - implementation 'com.github.jenly1314.UltraSwipeRefresh:refresh:1.1.0' + implementation 'com.github.jenly1314.UltraSwipeRefresh:refresh:1.1.1' // 经典样式的指示器 (可选) - implementation 'com.github.jenly1314.UltraSwipeRefresh:refresh-indicator-classic:1.1.0' + implementation 'com.github.jenly1314.UltraSwipeRefresh:refresh-indicator-classic:1.1.1' // Lottie动画指示器 (可选) - implementation 'com.github.jenly1314.UltraSwipeRefresh:refresh-indicator-lottie:1.1.0' + implementation 'com.github.jenly1314.UltraSwipeRefresh:refresh-indicator-lottie:1.1.1' // 进度条样式的指示器 (可选) - implementation 'com.github.jenly1314.UltraSwipeRefresh:refresh-indicator-progress:1.1.0' + implementation 'com.github.jenly1314.UltraSwipeRefresh:refresh-indicator-progress:1.1.1' ``` ## 使用 -### UltraSwipeRefreshTheme(v1.1.0新增) - -UltraSwipeRefreshTheme:主要用于统一管理全局默认配置。 - -> 通常情况下,一个App使用的刷新样式是统一的,如果你需要进行全局统一刷新组件的样式时,可以通过`UltraSwipeRefreshTheme.config`来动态修改`UltraSwipeRefresh`的全局默认配置。 - -#### UltraSwipeRefreshTheme使用示例 - -```kotlin -// 全局设置默认的滑动模式 -UltraSwipeRefreshTheme.config = UltraSwipeRefreshTheme.config.copy( - headerScrollMode = NestedScrollMode.Translate, - footerScrollMode = NestedScrollMode.Translate, -) -``` - ### UltraSwipeRefresh **Compose** 组件的使用大都比较直观,一般只需看一下 **Composable** 函数对应的参数说明基本就会使用了。 @@ -168,6 +152,22 @@ fun UltraSwipeRefreshSample() { > 使用小提示:**headerIndicator/footerIndicator** 与 **headerScrollMode/footerScrollMode** 组合使用才更配哦。 +### UltraSwipeRefreshTheme(v1.1.0新增) + +UltraSwipeRefreshTheme:主要用于统一管理全局默认配置。 + +> 通常情况下,一个App使用的刷新样式是统一的,如果你需要进行全局统一刷新组件的样式时,可以通过`UltraSwipeRefreshTheme.config`来动态修改`UltraSwipeRefresh`的全局默认配置。 + +#### UltraSwipeRefreshTheme使用示例 + +```kotlin +// 全局设置默认的滑动模式 +UltraSwipeRefreshTheme.config = UltraSwipeRefreshTheme.config.copy( + headerScrollMode = NestedScrollMode.Translate, + footerScrollMode = NestedScrollMode.Translate, +) +``` + ### 指示器样式 这里罗列一下目前 **UltraSwipeRefresh** 所包含的一些Header和Footer指示器样式,方便快速查找与参考。 @@ -198,6 +198,10 @@ fun UltraSwipeRefreshSample() { ## 版本记录 +#### v1.1.1 2024-4-20 +* 修复BUG:刷新状态变化太快时,导致”完成时的定格提示动画”不执行的问题。([#4]) +* 优化一些细节 + #### v1.1.0 2023-12-17 * 新增`UltraSwipeRefreshTheme`:用于统一管理全局默认配置 diff --git a/app/release/app-release.apk b/app/release/app-release.apk index 6f21f29..05e0939 100644 Binary files a/app/release/app-release.apk and b/app/release/app-release.apk differ diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json index 804c46f..9a3479f 100644 --- a/app/release/output-metadata.json +++ b/app/release/output-metadata.json @@ -11,8 +11,8 @@ "type": "SINGLE", "filters": [], "attributes": [], - "versionCode": 2, - "versionName": "1.1.0", + "versionCode": 3, + "versionName": "1.1.1", "outputFile": "app-release.apk" } ], diff --git a/gradle.properties b/gradle.properties index 4b5612f..2353003 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,8 +22,8 @@ kotlin.code.style=official # thereby reducing the size of the R class for that library android.nonTransitiveRClass=true -VERSION_NAME=1.1.0 -VERSION_CODE=2 +VERSION_NAME=1.1.1 +VERSION_CODE=3 GROUP=com.github.jenly1314.UltraSwipeRefresh POM_DESCRIPTION=UltraSwipeRefresh for Android diff --git a/refresh-indicator-classic/src/main/java/com/king/ultraswiperefresh/indicator/classic/ClassicRefreshIndicator.kt b/refresh-indicator-classic/src/main/java/com/king/ultraswiperefresh/indicator/classic/ClassicRefreshIndicator.kt index 28a1a37..1599bc5 100644 --- a/refresh-indicator-classic/src/main/java/com/king/ultraswiperefresh/indicator/classic/ClassicRefreshIndicator.kt +++ b/refresh-indicator-classic/src/main/java/com/king/ultraswiperefresh/indicator/classic/ClassicRefreshIndicator.kt @@ -73,40 +73,28 @@ internal fun ClassicRefreshIndicator( if (isFooter) { LaunchedEffect(state.footerState) { when (state.footerState) { - UltraSwipeFooterState.PullUpToLoad -> { - arrowDegrees.animateTo(180f) - } - UltraSwipeFooterState.ReleaseToLoad -> { arrowDegrees.animateTo(0f) } - else -> { - - } + else -> arrowDegrees.animateTo(180f) } } } else { LaunchedEffect(state.headerState) { when (state.headerState) { - UltraSwipeHeaderState.PullDownToRefresh -> { - arrowDegrees.animateTo(0f) - } - UltraSwipeHeaderState.ReleaseToRefresh -> { arrowDegrees.animateTo(180f) } - else -> { - - } + else -> arrowDegrees.animateTo(0f) } } } val alphaState = remember { derivedStateOf { - if ((state.indicatorOffset > 0f && !isFooter) || (state.indicatorOffset < 0f && isFooter)) { + if ((!isFooter && state.indicatorOffset > 0f) || (isFooter && state.indicatorOffset < 0f)) { 1f } else { 0f diff --git a/refresh-indicator-lottie/src/main/java/com/king/ultraswiperefresh/indicator/lottie/LottieRefreshIndicator.kt b/refresh-indicator-lottie/src/main/java/com/king/ultraswiperefresh/indicator/lottie/LottieRefreshIndicator.kt index 231116c..ec9bfaf 100644 --- a/refresh-indicator-lottie/src/main/java/com/king/ultraswiperefresh/indicator/lottie/LottieRefreshIndicator.kt +++ b/refresh-indicator-lottie/src/main/java/com/king/ultraswiperefresh/indicator/lottie/LottieRefreshIndicator.kt @@ -6,9 +6,7 @@ import androidx.compose.foundation.layout.height import androidx.compose.runtime.Composable import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha @@ -45,12 +43,14 @@ internal fun LottieRefreshIndicator( ) { val composition by rememberLottieComposition(spec = spec) - var isPlaying by remember { mutableStateOf(false) } - - isPlaying = if (isFooter) { - state.footerState == UltraSwipeFooterState.Loading - } else { - state.headerState == UltraSwipeHeaderState.Refreshing + val isPlaying by remember { + derivedStateOf { + if (isFooter) { + state.footerState == UltraSwipeFooterState.Loading + } else { + state.headerState == UltraSwipeHeaderState.Refreshing + } + } } val progress by animateLottieCompositionAsState( @@ -64,7 +64,7 @@ internal fun LottieRefreshIndicator( val alphaState = remember { derivedStateOf { - if ((state.indicatorOffset > 0f && !isFooter) || (state.indicatorOffset < 0f && isFooter)) { + if ((!isFooter && state.indicatorOffset > 0f) || (isFooter && state.indicatorOffset < 0f)) { 1f } else { 0f diff --git a/refresh-indicator-progress/src/main/java/com/king/ultraswiperefresh/indicator/progress/ProgressRefreshIndicator.kt b/refresh-indicator-progress/src/main/java/com/king/ultraswiperefresh/indicator/progress/ProgressRefreshIndicator.kt index 0523962..b0028d8 100644 --- a/refresh-indicator-progress/src/main/java/com/king/ultraswiperefresh/indicator/progress/ProgressRefreshIndicator.kt +++ b/refresh-indicator-progress/src/main/java/com/king/ultraswiperefresh/indicator/progress/ProgressRefreshIndicator.kt @@ -38,14 +38,20 @@ internal fun ProgressRefreshIndicator( val progressState = remember { derivedStateOf { - if (isFooter) { - state.indicatorOffset.div( - state.loadMoreTrigger.coerceAtMost(-1f) - ).coerceIn(0f, 1f) - } else { - state.indicatorOffset.div( - state.refreshTrigger.coerceAtLeast(1f) - ).coerceIn(0f, 1f) + when { + !isFooter && state.indicatorOffset > 0f -> { + state.indicatorOffset.div( + state.refreshTrigger.coerceAtLeast(1f) + ).coerceIn(0f, 1f) + } + + isFooter && state.indicatorOffset < 0f -> { + state.indicatorOffset.div( + state.loadMoreTrigger.coerceAtMost(-1f) + ).coerceIn(0f, 1f) + } + + else -> 0f } } } @@ -67,7 +73,7 @@ internal fun ProgressRefreshIndicator( Box(modifier = modifier) { Box( Modifier - .alpha(if (progressState.value == 0f) 0f else 1f) + .alpha(if (progressState.value > 0f) 1f else 0f) .fillMaxWidth() .height(height) .drawWithCache { diff --git a/refresh/src/main/java/com/king/ultraswiperefresh/UltraSwipeRefresh.kt b/refresh/src/main/java/com/king/ultraswiperefresh/UltraSwipeRefresh.kt index f2d4f1a..bd989ba 100644 --- a/refresh/src/main/java/com/king/ultraswiperefresh/UltraSwipeRefresh.kt +++ b/refresh/src/main/java/com/king/ultraswiperefresh/UltraSwipeRefresh.kt @@ -83,16 +83,16 @@ fun UltraSwipeRefresh( val updatedOnRefresh = rememberUpdatedState(onRefresh) val updateOnLoadMore = rememberUpdatedState(onLoadMore) - Box(modifier.clipToBounds()) { + Box(modifier) { RefreshSubComposeLayout( + refreshEnabled = refreshEnabled, + loadMoreEnabled = loadMoreEnabled, headerIndicator = { headerIndicator(state) }, footerIndicator = { footerIndicator(state) }, - refreshEnabled = refreshEnabled, - loadMoreEnabled = loadMoreEnabled, ) { headerHeight, footerHeight -> val nestedScrollConnection = remember(state, coroutineScope) { @@ -127,6 +127,11 @@ fun UltraSwipeRefresh( state.isLoading -> state.animateOffsetTo(-footerHeight.toFloat()) state.headerState == UltraSwipeHeaderState.Refreshing || state.footerState == UltraSwipeFooterState.Loading -> { state.isFinishing = true + if (state.indicatorOffset > headerHeight) { + state.animateOffsetTo(headerHeight.toFloat()) + } else if (state.indicatorOffset < -footerHeight) { + state.animateOffsetTo(-footerHeight.toFloat()) + } delay(finishDelayMillis) state.animateOffsetTo(0f) } @@ -152,13 +157,14 @@ fun UltraSwipeRefresh( } } - Box(modifier = Modifier.nestedScroll(nestedScrollConnection)) { + Box(modifier = Modifier.nestedScroll(nestedScrollConnection).clipToBounds()) { Box(modifier = Modifier .align(Alignment.TopCenter) .graphicsLayer { translationY = obtainHeaderOffset(state, headerScrollMode, headerHeight) } .zIndex(obtainZIndex(headerScrollMode)) + ) { if (refreshEnabled) { headerIndicator(state) @@ -378,10 +384,8 @@ private fun rememberVibrator(): Vibrator { @Suppress("DEPRECATION") private fun Vibrator.vibrate() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - this.vibrate( - VibrationEffect.createOneShot(20, VibrationEffect.DEFAULT_AMPLITUDE) - ) + vibrate(VibrationEffect.createOneShot(20, VibrationEffect.DEFAULT_AMPLITUDE)) } else { - this.vibrate(20) + vibrate(20) } } \ No newline at end of file diff --git a/refresh/src/main/java/com/king/ultraswiperefresh/UltraSwipeRefreshNestedScrollConnection.kt b/refresh/src/main/java/com/king/ultraswiperefresh/UltraSwipeRefreshNestedScrollConnection.kt index 88dc0b0..ca81b2b 100644 --- a/refresh/src/main/java/com/king/ultraswiperefresh/UltraSwipeRefreshNestedScrollConnection.kt +++ b/refresh/src/main/java/com/king/ultraswiperefresh/UltraSwipeRefreshNestedScrollConnection.kt @@ -73,16 +73,23 @@ internal class UltraSwipeRefreshNestedScrollConnection( } override suspend fun onPreFling(available: Velocity): Velocity { - if (!(state.isRefreshing || state.isLoading || state.isFinishing)) { - when { - refreshEnabled && state.isExceededRefreshTrigger() -> onRefresh() - loadMoreEnabled && state.isExceededLoadMoreTrigger() -> onLoadMore() - state.indicatorOffset != 0f && !state.isSwipeInProgress -> state.animateOffsetTo(0f) - } + if (state.isRefreshing || state.isLoading || state.isFinishing) { + state.isSwipeInProgress = false + return available + } + when { + refreshEnabled && state.isExceededRefreshTrigger() -> onRefresh() + loadMoreEnabled && state.isExceededLoadMoreTrigger() -> onLoadMore() + state.indicatorOffset != 0f && !state.isSwipeInProgress -> state.animateOffsetTo(0f) } - state.isSwipeInProgress = false - return super.onPreFling(available) + return Velocity.Zero } + override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity { + if (state.isRefreshing || state.isLoading || state.isFinishing) { + return available + } + return Velocity.Zero + } } \ No newline at end of file diff --git a/refresh/src/main/java/com/king/ultraswiperefresh/UltraSwipeRefreshState.kt b/refresh/src/main/java/com/king/ultraswiperefresh/UltraSwipeRefreshState.kt index 860e0e7..a2042ab 100644 --- a/refresh/src/main/java/com/king/ultraswiperefresh/UltraSwipeRefreshState.kt +++ b/refresh/src/main/java/com/king/ultraswiperefresh/UltraSwipeRefreshState.kt @@ -124,6 +124,10 @@ class UltraSwipeRefreshState(isRefreshing: Boolean, isLoading: Boolean) { */ internal suspend fun animateOffsetTo(offset: Float) { mutatorMutex.mutate { + if(!isFinishing) { + updateHeaderState() + updateFooterState() + } _indicatorOffset.animateTo(offset) { if (indicatorOffset == 0f && isFinishing) { isFinishing = false @@ -131,10 +135,6 @@ class UltraSwipeRefreshState(isRefreshing: Boolean, isLoading: Boolean) { updateFooterState() } } - if(!isFinishing) { - updateHeaderState() - updateFooterState() - } } } diff --git a/refresh/src/main/java/com/king/ultraswiperefresh/indicator/SwipeRefreshIndicator.kt b/refresh/src/main/java/com/king/ultraswiperefresh/indicator/SwipeRefreshIndicator.kt index f036b85..e68d755 100644 --- a/refresh/src/main/java/com/king/ultraswiperefresh/indicator/SwipeRefreshIndicator.kt +++ b/refresh/src/main/java/com/king/ultraswiperefresh/indicator/SwipeRefreshIndicator.kt @@ -156,7 +156,7 @@ internal fun SwipeRefreshIndicator( val alphaState = remember { derivedStateOf { - if ((state.indicatorOffset > 0f && !isFooter) || (state.indicatorOffset < 0f && isFooter)) { + if ((!isFooter && state.indicatorOffset > 0f) || (isFooter && state.indicatorOffset < 0f)) { 1f } else { 0f @@ -175,39 +175,29 @@ internal fun SwipeRefreshIndicator( .alpha(alphaState.value) .size(size = sizes.size) .graphicsLayer { - if (isFooter) { - val scaleFraction = - if (scale && state.footerState != UltraSwipeFooterState.Loading) { - val progress = - state.indicatorOffset / state.loadMoreTrigger.coerceAtMost(-1f) + val scaleFraction = when { + !scale -> 1f + !isFooter && state.headerState != UltraSwipeHeaderState.Refreshing -> { + LinearOutSlowInEasing + .transform( + state.indicatorOffset.div(state.refreshTrigger.coerceAtLeast(1f)) + ) + .coerceIn(0f, 1f) + } - // We use LinearOutSlowInEasing to speed up the scale in - LinearOutSlowInEasing - .transform(progress) - .coerceIn(0f, 1f) - } else 1f + isFooter && state.footerState != UltraSwipeFooterState.Loading -> { + LinearOutSlowInEasing + .transform( + state.indicatorOffset.div(state.loadMoreTrigger.coerceAtMost(-1f)) + ) + .coerceIn(0f, 1f) + } - scaleX = scaleFraction - scaleY = scaleFraction - - } else { - // Translate the indicator according to the slingshot - translationY = 0f - - val scaleFraction = - if (scale && state.headerState != UltraSwipeHeaderState.Refreshing) { - val progress = - state.indicatorOffset / state.refreshTrigger.coerceAtLeast(1f) - - // We use LinearOutSlowInEasing to speed up the scale in - LinearOutSlowInEasing - .transform(progress) - .coerceIn(0f, 1f) - } else 1f - - scaleX = scaleFraction - scaleY = scaleFraction + else -> 1f } + + scaleX = scaleFraction + scaleY = scaleFraction }, shape = shape, color = backgroundColor, @@ -267,10 +257,7 @@ internal fun SwipeRefreshIndicator( modifier = Modifier.size(circleSize), ) } else { - Image( - painter = painter, - contentDescription = "Indicator" - ) + Image(painter = painter, contentDescription = "Indicator") } } } diff --git a/versions.gradle b/versions.gradle index 67533f1..0a9a7b4 100644 --- a/versions.gradle +++ b/versions.gradle @@ -1,7 +1,7 @@ // App def app_version = [:] -app_version.versionCode = 2 -app_version.versionName = "1.1.0" +app_version.versionCode = 3 +app_version.versionName = "1.1.1" ext.app_version = app_version // build version