pref: 加载更多防抖
This commit is contained in:
parent
5248ce6cf8
commit
7925c36f07
|
|
@ -2,15 +2,30 @@ package com.huanchengfly.tieba.post.ui.widgets.compose
|
||||||
|
|
||||||
import androidx.compose.animation.animateContentSize
|
import androidx.compose.animation.animateContentSize
|
||||||
import androidx.compose.foundation.gestures.Orientation
|
import androidx.compose.foundation.gestures.Orientation
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.IntrinsicSize
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.offset
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.*
|
import androidx.compose.material.CircularProgressIndicator
|
||||||
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
|
import androidx.compose.material.FractionalThreshold
|
||||||
|
import androidx.compose.material.Surface
|
||||||
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.rememberUpdatedState
|
import androidx.compose.runtime.rememberUpdatedState
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
|
|
@ -27,12 +42,17 @@ import androidx.compose.ui.unit.dp
|
||||||
import com.huanchengfly.tieba.post.R
|
import com.huanchengfly.tieba.post.R
|
||||||
import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme
|
import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme
|
||||||
import com.huanchengfly.tieba.post.ui.common.theme.compose.loadMoreIndicator
|
import com.huanchengfly.tieba.post.ui.common.theme.compose.loadMoreIndicator
|
||||||
|
import kotlinx.coroutines.FlowPreview
|
||||||
|
import kotlinx.coroutines.channels.BufferOverflow
|
||||||
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
|
import kotlinx.coroutines.flow.sample
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
private val LoadDistance = 70.dp
|
private val LoadDistance = 70.dp
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class, FlowPreview::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun LoadMoreLayout(
|
fun LoadMoreLayout(
|
||||||
isLoading: Boolean,
|
isLoading: Boolean,
|
||||||
|
|
@ -50,17 +70,42 @@ fun LoadMoreLayout(
|
||||||
) {
|
) {
|
||||||
val loadDistance = with(LocalDensity.current) { LoadDistance.toPx() }
|
val loadDistance = with(LocalDensity.current) { LoadDistance.toPx() }
|
||||||
|
|
||||||
|
val curOnLoadMore by rememberUpdatedState(newValue = onLoadMore)
|
||||||
|
var lastTriggerTime by remember { mutableStateOf(0L) }
|
||||||
|
var waitingStateReset by remember { mutableStateOf(false) }
|
||||||
|
val loadMoreFlow = remember {
|
||||||
|
MutableSharedFlow<Long>(
|
||||||
|
extraBufferCapacity = 1,
|
||||||
|
onBufferOverflow = BufferOverflow.DROP_LATEST
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
DisposableEffect(Unit) {
|
||||||
|
val job = coroutineScope.launch {
|
||||||
|
loadMoreFlow
|
||||||
|
.sample(500)
|
||||||
|
.collect {
|
||||||
|
curOnLoadMore()
|
||||||
|
waitingStateReset = true
|
||||||
|
lastTriggerTime = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onDispose { job.cancel() }
|
||||||
|
}
|
||||||
|
|
||||||
val canLoadMore = remember(enableLoadMore, loadEnd) { enableLoadMore && !loadEnd }
|
val canLoadMore = remember(enableLoadMore, loadEnd) { enableLoadMore && !loadEnd }
|
||||||
val curIsLoading by rememberUpdatedState(newValue = isLoading)
|
val curIsLoading by rememberUpdatedState(newValue = isLoading)
|
||||||
val curCanLoadMore by rememberUpdatedState(newValue = canLoadMore)
|
val curCanLoadMore by rememberUpdatedState(newValue = canLoadMore)
|
||||||
|
|
||||||
var waitingStateReset by remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
val swipeableState = rememberSwipeableState(false) { newValue ->
|
val swipeableState = rememberSwipeableState(false) { newValue ->
|
||||||
if (newValue && !curIsLoading && curCanLoadMore) {
|
if (newValue && !curIsLoading && curCanLoadMore) {
|
||||||
onLoadMore()
|
val curTime = System.currentTimeMillis()
|
||||||
waitingStateReset = true
|
coroutineScope.launch {
|
||||||
true
|
loadMoreFlow.emit(curTime)
|
||||||
|
}
|
||||||
|
curTime - lastTriggerTime >= 500
|
||||||
} else !newValue
|
} else !newValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,6 +116,8 @@ fun LoadMoreLayout(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(isLoading) { swipeableState.animateTo(isLoading) }
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.nestedScroll(swipeableState.LoadPreUpPostDownNestedScrollConnection)
|
.nestedScroll(swipeableState.LoadPreUpPostDownNestedScrollConnection)
|
||||||
|
|
@ -96,8 +143,6 @@ fun LoadMoreLayout(
|
||||||
indicator(isLoading, loadEnd, swipeableState.targetValue)
|
indicator(isLoading, loadEnd, swipeableState.targetValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(isLoading) { swipeableState.animateTo(isLoading) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue