初始代码提交

This commit is contained in:
2026-01-14 10:36:27 +08:00
parent 600aa4dbb0
commit 196cacfe5a
268 changed files with 22545 additions and 2 deletions
@@ -0,0 +1,223 @@
package com.sw.inbound.utils
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
/**
* Jetpack Compose 交互工具集
* 包含快速点击过滤、防抖、节流、双击检测、长按检测等功能
*/
object InteractionUtils {
// ======================== 点击过滤 ========================
/**
* 快速点击过滤器
* @param minInterval 最小点击间隔时间(毫秒),默认500ms
*/
class ClickFilter(private val minInterval: Long = 500L) {
private var lastClickTime: Long = 0
/**
* 处理点击事件
* @return Boolean 是否允许此次点击(true=允许,false=拦截)
*/
fun processClick(): Boolean {
val currentTime = System.currentTimeMillis()
return if (currentTime - lastClickTime > minInterval) {
lastClickTime = currentTime
true
} else {
false
}
}
/**
* 处理点击事件(带回调)
*/
fun processClick(block: () -> Unit) {
if (processClick()) {
block()
}
}
}
/**
* 记住点击过滤器
*/
@Composable
fun rememberClickFilter(minInterval: Long = 500L): ClickFilter {
return remember { ClickFilter(minInterval) }
}
// ======================== 防抖处理 ========================
/**
* 防抖工具类
* @param delayMillis 防抖延迟时间(毫秒)
*/
class Debouncer(private val delayMillis: Long) {
private var lastActionTime = 0L
/**
* 执行防抖操作
* @param block 要执行的代码块
* @return Boolean 是否实际执行了操作
*/
fun debounce(block: () -> Unit): Boolean {
val currentTime = System.currentTimeMillis()
if (currentTime - lastActionTime >= delayMillis) {
lastActionTime = currentTime
block()
return true
}
return false
}
}
// ======================== 双击检测 ========================
/**
* 双击检测器
*/
class DoubleClickDetector(
private val timeout: Long = 500L,
private val onSingleClick: () -> Unit = {},
private val onDoubleClick: () -> Unit
) {
private var clickCount by mutableIntStateOf(0)
private var lastClickTime by mutableLongStateOf(0L)
/**
* 处理点击事件
*/
fun processClick(coroutineScope: CoroutineScope) {
val currentTime = System.currentTimeMillis()
if (currentTime - lastClickTime < timeout) {
clickCount++
if (clickCount == 2) {
onDoubleClick()
clickCount = 0
}
} else {
clickCount = 1
coroutineScope.launch {
delay(timeout)
if (clickCount == 1) {
onSingleClick()
}
clickCount = 0
}
}
lastClickTime = currentTime
}
}
/**
* 记住双击检测器
*/
@Composable
fun rememberDoubleClickDetector(
timeout: Long = 300L,
onSingleClick: () -> Unit = {},
onDoubleClick: () -> Unit
): () -> Unit {
val detector = remember { DoubleClickDetector(timeout, onSingleClick, onDoubleClick) }
val scope = rememberCoroutineScope()
return {
detector.processClick(scope)
}
}
// ======================== 长按检测 ========================
/**
* 长按检测器
*/
class LongPressDetector(
private val delay: Long = 1000L,
private val onLongPress: () -> Unit,
private val onClick: () -> Unit = {}
) {
private var pressJob: Job? = null
/**
* 处理按压事件
*/
fun handlePress(coroutineScope: CoroutineScope) {
pressJob = coroutineScope.launch {
delay(delay)
onLongPress()
}
}
/**
* 处理释放事件
*/
fun handleRelease() {
pressJob?.cancel()
pressJob = null
onClick()
}
}
/**
* 记住长按检测器
*/
@Composable
fun rememberLongPressDetector(
delay: Long = 1000L,
onLongPress: () -> Unit,
onClick: () -> Unit = {}
): Pair<() -> Unit, () -> Unit> {
val detector = remember { LongPressDetector(delay, onLongPress, onClick) }
val scope = rememberCoroutineScope()
return Pair(
first = { detector.handlePress(scope) },
second = { detector.handleRelease() }
)
}
// ======================== 组合工具 ========================
/**
* 带状态的按钮控制器
*/
class StatefulButtonController {
var isLoading by mutableStateOf(false)
private val clickFilter = ClickFilter()
/**
* 处理按钮点击
*/
suspend fun handleClick(block: suspend () -> Unit) {
if (clickFilter.processClick()) {
isLoading = true
try {
block()
} finally {
isLoading = false
}
}
}
}
/**
* 记住带状态的按钮控制器
*/
@Composable
fun rememberStatefulButtonController(): StatefulButtonController {
return remember { StatefulButtonController() }
}
}