kotlin 不能在Jetpack compose的任何组件上使用combinedClickable和pointerInput

x759pob2  于 2023-04-07  发布在  Kotlin
关注(0)|答案(1)|浏览(199)

我试图使一个浮动ActionButton,让我使用onLongClick和手势检测的情况下是拖了起来。只是创建电报或新闻记录按钮的行为。
测试1使用Material3中的FloatingActionButton不起作用,原因是长时间单击:

FloatingActionButton(
            modifier = Modifier
                .size(48.dp)
                .combinedClickable(
                    onClick = {
                        if (!textEmpty) {
                            onMessageChange(input.value.text)
                            input.value = TextFieldValue("")
                        }

                        if (recordingIsLock) {
                            stopRecord()
                        }
                    },
                    onLongClick = {
                        if (textEmpty) {
                            record()
                        }
                    }
                )
                .pointerInput(Unit) {
                    detectVerticalDragGestures(
                        onDragStart = {},
                        onDragCancel = {},
                        onDragEnd = {
                            if (!recordingIsLock) {
                                btnIndicatorHeight = 0F
                            }
                        },
                        onVerticalDrag = { change, dragAmount ->
                            // saber si no hay nada escrito
                            // saber si el drag es hacia arriba
                            // saber si esta grabando
                            if (textEmpty && change.position.y < 0 && dragAmount < 0 && isRecording) {
                                val aux = kotlin.math.abs(dragAmount)

                                btnIndicatorHeight += if (
                                    !recordingIsLock &&
                                    btnIndicatorHeight < 48
                                ) {
                                    println("!!!!")
                                    aux / 10
                                } else if (btnIndicatorHeight >= 48) {
                                    if (!recordingIsLock) {
                                        recordingIsLock = true
                                    }
                                    0F
                                } else {
                                    0F
                                }
                            }
                        })
                },
            onClick = {}
        ) {
            Icon(
                modifier = Modifier.size(24.dp),
                tint = MaterialTheme.colorScheme.background,
                imageVector = if (textEmpty) Icons.Filled.Mic else Icons.Filled.Send,
                contentDescription = null
            )

            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .height(btnIndicatorHeight.dp)
                    .background(color = MaterialTheme.colorScheme.primary),
                contentAlignment = Alignment.Center
            ) {
                if (!recordingIsLock)
                    Icon(
                        tint = Color.White,
                        imageVector = Icons.Outlined.Lock,
                        contentDescription = null
                    )
                else
                    LottieAnimation(
                        modifier = Modifier.size(30.dp),
                        composition = recordingAnimationComposition,
                        iterations = Int.MAX_VALUE
                    )
            }
        }

测试2:创建自定义组件不会执行拖动行为。

ElevatedCard(
    modifier = modifier
        .size(48.dp)
                .combinedClickable(
                    onClick = {
                        if (!textEmpty) {
                            onMessageChange(input.value.text)
                            input.value = TextFieldValue("")
                        }

                        if (recordingIsLock) {
                            stopRecord()
                        }
                    },
                    onLongClick = {
                        if (textEmpty) {
                            record()
                        }
                    }
                )
                .pointerInput(Unit) {
                    detectVerticalDragGestures(
                        onDragStart = {},
                        onDragCancel = {},
                        onDragEnd = {
                            if (!recordingIsLock) {
                                btnIndicatorHeight = 0F
                            }
                        },
                        onVerticalDrag = { change, dragAmount ->
                            // saber si no hay nada escrito
                            // saber si el drag es hacia arriba
                            // saber si esta grabando
                            if (textEmpty && change.position.y < 0 && dragAmount < 0 && isRecording) {
                                val aux = kotlin.math.abs(dragAmount)

                                btnIndicatorHeight += if (
                                    !recordingIsLock &&
                                    btnIndicatorHeight < 48
                                ) {
                                    println("!!!!")
                                    aux / 10
                                } else if (btnIndicatorHeight >= 48) {
                                    if (!recordingIsLock) {
                                        recordingIsLock = true
                                    }
                                    0F
                                } else {
                                    0F
                                }
                            }
                        })
                }
        .background(
            color = MaterialTheme.colorScheme.surface,
            shape = RoundedCornerShape(10.dp)
        )
) {
    Box(contentAlignment = Alignment.Center) {
        component()
    }
}
x7rlezfr

x7rlezfr1#

我找到了创建我的自定义按钮的方法。它有西班牙语的注解,我相信你们都可以像我一样翻译你的答案;):

import android.os.CountDownTimer
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.gestures.detectVerticalDragGestures
import androidx.compose.foundation.indication
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.PressInteraction
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Mic
import androidx.compose.material.icons.filled.Send
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.unit.dp
import com.airbnb.lottie.LottieProperty
import com.airbnb.lottie.SimpleColorFilter
import com.airbnb.lottie.compose.*
import cu.todus.android.R
import cu.z17.views.button.invertedBounceClick

@Composable
fun ChatSendButton(
    textEmpty: Boolean,
    recordingIsLock: MutableState<Boolean>,
    isRecording: MutableState<Boolean>,
    btnIndicatorHeight: MutableState<Float>,
    record: () -> Unit,
    stopRecord: () -> Unit,
    onMessageChange: () -> Unit
) {
    var isDragging by remember {
        mutableStateOf(false)
    }

    val recordingAnimationComposition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.recording_lottie_anim))
    //var tapped by remember { mutableStateOf(false) }
    val interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }

    val dynamicProperties = rememberLottieDynamicProperties(
        rememberLottieDynamicProperty(
            property = LottieProperty.COLOR_FILTER,
            value = SimpleColorFilter(MaterialTheme.colorScheme.background.toArgb()),
            keyPath = arrayOf("**")
        ),
    )

    var time by remember {
        mutableStateOf(1000L)
    }

    Surface(
        modifier = Modifier
            .size(48.dp)
            .invertedBounceClick()
            .graphicsLayer {
                if (!recordingIsLock.value)
                    this.translationY -= btnIndicatorHeight.value * 6
                else this.translationY = 0F
            }
            // Modificador para arrastrar el botón
            .pointerInput(Unit) {
                detectVerticalDragGestures(
                    onDragStart = {
                        isDragging = true
                    },
                    onDragCancel = {
                        isDragging = false
                        if (!recordingIsLock.value) {
                            btnIndicatorHeight.value = 0F
                            stopRecord()
                        }
                    },
                    onDragEnd = {
                        isDragging = false
                        if (!recordingIsLock.value) {
                            btnIndicatorHeight.value = 0F
                            stopRecord()
                        }
                    },
                    onVerticalDrag = { change, dragAmount ->
                        // saber si no hay nada escrito
                        // saber si el drag es hacia arriba
                        // saber si esta grabando
                        if (textEmpty && change.position.y < 0 && dragAmount < 0 && isRecording.value) {
                            val aux = kotlin.math.abs(dragAmount)

                            btnIndicatorHeight.value += if (
                                !recordingIsLock.value &&
                                btnIndicatorHeight.value < 48
                            ) {
                                aux / 10
                            } else if (btnIndicatorHeight.value >= 48) {
                                if (!recordingIsLock.value) {
                                    recordingIsLock.value = true
                                }
                                0F
                            } else {
                                0F
                            }
                        }
                    })
            }
            // Modificador para detectar long press y arrastre al mismo tiempo
            .pointerInput(Unit) {
                detectTapGestures(
                    onPress = { offset ->
                        val press = PressInteraction.Press(offset)
                        interactionSource.emit(press)

                        val countDownTimer = object : CountDownTimer(time, 10) {
                            override fun onTick(millisUntilFinished: Long) {
                                time -= 10
                            }

                            override fun onFinish() {
                                time = 500
                                record()
                                this.cancel()
                            }
                        }
                        countDownTimer.start()

                        tryAwaitRelease()
                        interactionSource.emit(PressInteraction.Release(press))

                        if (!isDragging) stopRecord()

                        countDownTimer.cancel()
                    },
                    onTap = {
                        if (!textEmpty) {
                            onMessageChange()
                        }

                        if (recordingIsLock.value) {
                            stopRecord()
                        }
                    }
                )
            }
            .clip(RoundedCornerShape(10.dp))
            .indication(interactionSource, LocalIndication.current)
    ) {
        Box(
            modifier = Modifier
                .fillMaxSize(),
            contentAlignment = Alignment.Center
        ) {
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .height(btnIndicatorHeight.value.dp)
                    .background(color = MaterialTheme.colorScheme.primary),
                contentAlignment = Alignment.Center
            ) {
                if (isDragging)
                    Icon(
                        tint = Color.White,
                        imageVector = Icons.Outlined.Lock,
                        contentDescription = null
                    )
            }

            if (!isRecording.value)
                Icon(
                    modifier = Modifier.size(24.dp),
                    tint = MaterialTheme.colorScheme.background,
                    imageVector = if (textEmpty) Icons.Filled.Mic else Icons.Filled.Send,
                    contentDescription = null
                )
            else if (isRecording.value && !isDragging)
                LottieAnimation(
                    modifier = Modifier.fillMaxSize(),
                    composition = recordingAnimationComposition,
                    iterations = Int.MAX_VALUE,
                    dynamicProperties = dynamicProperties
                )
        }
    }
}

相关问题