录音取消逻辑

This commit is contained in:
renhaoting 2025-10-27 14:28:46 +08:00
parent 75ab00be93
commit 103a91e7c1
4 changed files with 66 additions and 53 deletions

View File

@ -1,6 +1,7 @@
package com.remax.visualnovel.ui.chat package com.remax.visualnovel.ui.chat
import android.graphics.Point
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
@ -25,7 +26,6 @@ import com.remax.visualnovel.extension.toast
import com.remax.visualnovel.manager.nim.NimManager import com.remax.visualnovel.manager.nim.NimManager
import com.remax.visualnovel.ui.chat.setting.model.ChatModelDialog import com.remax.visualnovel.ui.chat.setting.model.ChatModelDialog
import com.remax.visualnovel.ui.chat.ui.HoldToTalkDialog import com.remax.visualnovel.ui.chat.ui.HoldToTalkDialog
import com.remax.visualnovel.ui.wallet.manager.WalletManager
import com.remax.visualnovel.utils.RecordHelper import com.remax.visualnovel.utils.RecordHelper
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -90,14 +90,21 @@ class ChatActivity : BaseBindingActivity<ActivityActorChatBinding>() {
private fun initInputPanelEvents() { private fun initInputPanelEvents() {
with(binding.inputPanel) { with(binding.inputPanel) {
holdToTalk({ holdToTalk(
mRecordAssist.startRecording() {
}) { mRecordAssist.startRecording()
mRecordAssist.stopTalk() },
} {
mRecordAssist.stopTalk()
},
touchPosCallback = { point ->
mRecordAssist.onTouchPointChanged(point)
}
)
} }
} }
/** /**
* 检查麦克风权限 * 检查麦克风权限
*/ */
@ -179,6 +186,7 @@ class ChatActivity : BaseBindingActivity<ActivityActorChatBinding>() {
inner class RecordAssist { inner class RecordAssist {
private var mIsCancelled = false
private var recordJob: Job? = null private var recordJob: Job? = null
private val recordHelper by lazy { private val recordHelper by lazy {
@ -210,8 +218,8 @@ class ChatActivity : BaseBindingActivity<ActivityActorChatBinding>() {
private fun startTalk() { private fun startTalk() {
val maxTalkTime = 60 val maxTalkTime = 60
val minTalkTime = 1 val minTalkTime = 1
var recordingProgress = 0 var recordingProgress = 0
mIsCancelled = false
holdToTalkDialog.show() holdToTalkDialog.show()
recordHelper.startRecording(this@ChatActivity, { recordHelper.startRecording(this@ChatActivity, {
@ -223,33 +231,41 @@ class ChatActivity : BaseBindingActivity<ActivityActorChatBinding>() {
}) })
}, { }, {
if (recordingProgress >= minTalkTime) { if (!mIsCancelled) {
Timber.i("startRecording onStop: ${recordHelper.getFilename()}") if (recordingProgress >= minTalkTime) {
Timber.i("startRecording onStop: ${recordHelper.getFilename()}")
launchAndLoadingCollect({ launchAndLoadingCollect({
chatViewModel.voiceASR(recordHelper.getFilename()) chatViewModel.voiceASR(recordHelper.getFilename())
}) { }) {
onSuccess = { onSuccess = {
if (!it?.content.isNullOrBlank()) { if (!it?.content.isNullOrBlank()) {
chatViewModel.sendMsg(it.content, errorCallback = sendMsgErrorCallback) chatViewModel.sendMsg(it.content, errorCallback = sendMsgErrorCallback)
}
} }
} }
}
} else { } else {
//录音最少1秒 showToast(R.string.min_voice_time) //录音最少1秒
showToast(R.string.min_voice_time) }
} }
}) })
} }
fun stopTalk() { fun stopTalk() {
mIsCancelled = holdToTalkDialog.isTouchInCancelArea;
holdToTalkDialog.dismiss() holdToTalkDialog.dismiss()
recordJob?.cancel() recordJob?.cancel()
recordHelper.stopRecording() recordHelper.stopRecording()
} }
fun onTouchPointChanged(point: Point) {
if (holdToTalkDialog.isShowing) {
holdToTalkDialog.onTouchPointChanged(point)
}
}
} }
} }

View File

@ -2,6 +2,7 @@ package com.remax.visualnovel.ui.chat
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.graphics.Point
import android.util.AttributeSet import android.util.AttributeSet
import android.view.MotionEvent import android.view.MotionEvent
import android.widget.FrameLayout import android.widget.FrameLayout
@ -82,7 +83,7 @@ class InputPanel @JvmOverloads constructor(context: Context, attrs: AttributeSet
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
fun holdToTalk(callback: () -> Unit, cancelCallback: () -> Unit) { fun holdToTalk(callback: () -> Unit, cancelCallback: () -> Unit, touchPosCallback: (point: Point) -> Unit) {
binding.ivHold2talk.run { binding.ivHold2talk.run {
setOnTouchListener { v, event -> setOnTouchListener { v, event ->
when (event.action) { when (event.action) {
@ -93,10 +94,15 @@ class InputPanel @JvmOverloads constructor(context: Context, attrs: AttributeSet
MotionEvent.ACTION_UP -> { MotionEvent.ACTION_UP -> {
cancelCallback.invoke() cancelCallback.invoke()
} }
MotionEvent.ACTION_MOVE -> {
touchPosCallback.invoke(Point(event.rawX.toInt(), event.rawY.toInt()))
}
} }
true true
} }
} }
} }
} }

View File

@ -1,68 +1,58 @@
package com.remax.visualnovel.ui.chat.ui package com.remax.visualnovel.ui.chat.ui
import android.content.Context import android.content.Context
import android.graphics.Point
import android.graphics.Rect import android.graphics.Rect
import android.view.MotionEvent
import android.view.View
import androidx.annotation.VisibleForTesting
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.remax.visualnovel.R import com.remax.visualnovel.R
import com.remax.visualnovel.databinding.DialogHoldToTalkBinding import com.remax.visualnovel.databinding.DialogHoldToTalkBinding
import com.remax.visualnovel.widget.dialoglib.LBindingDialog import com.remax.visualnovel.widget.dialoglib.LBindingDialog
/**
* Created by HJW on 2025/8/16
*/
class HoldToTalkDialog(context: Context) : class HoldToTalkDialog(context: Context) :
LBindingDialog<DialogHoldToTalkBinding>(context, DialogHoldToTalkBinding::inflate) { LBindingDialog<DialogHoldToTalkBinding>(context, DialogHoldToTalkBinding::inflate) {
var isTouchInCancelArea = false
fun build(): HoldToTalkDialog { fun build(): HoldToTalkDialog {
with() with()
setBottom() setBottom()
setBgColorToken(R.string.color_transparent) setBgColorToken(R.string.color_transparent)
setMaskValue(0f) setMaskValue(0f)
initRootTouchEvent()
show() show()
return this return this
} }
private fun initRootTouchEvent() {
with(binding.root) {
fun onTouchEvent(event: MotionEvent): Boolean {
val x = event.x.toInt()
val y = event.y.toInt()
when (event.actionMasked) {
MotionEvent.ACTION_MOVE -> {
updateStateUI(event)
}
}
return false
}
}
}
private fun isInValidArea(event: MotionEvent) : Boolean { fun onTouchPointChanged(point: Point) {
val rect = Rect()
binding.viewRelease.getHitRect(rect)
return rect.contains(event.rawX.toInt(), event.rawY.toInt())
}
private fun updateStateUI(event: MotionEvent) {
with (binding) { with (binding) {
when (isInValidArea(event)) { isTouchInCancelArea = !getTouchValidArea().contains(point.x, point.y)
true -> { when (isTouchInCancelArea) {
false -> {
viewRelease.setBackgroundResource(R.mipmap.bg_recording_normal) viewRelease.setBackgroundResource(R.mipmap.bg_recording_normal)
cancelHintRoot.isVisible = true cancelHintRoot.isVisible = true
tvRelease.text = context.resources.getString(R.string.release_to_send)
} }
false -> { true -> {
viewRelease.setBackgroundResource(R.mipmap.bg_recording_cancel) viewRelease.setBackgroundResource(R.mipmap.bg_recording_cancel)
cancelHintRoot.isVisible = false cancelHintRoot.isVisible = false
tvRelease.text = context.resources.getString(R.string.release_to_cancel)
} }
} }
} }
} }
private fun getTouchValidArea(): Rect {
val location = IntArray(2)
binding.viewRelease.getLocationOnScreen(location)
return Rect(
location[0],
location[1],
location[0] + binding.viewRelease.width,
location[1] + binding.viewRelease.height
)
}
} }

View File

@ -337,7 +337,7 @@
<string name="prompt">Prompt</string> <string name="prompt">Prompt</string>
<string name="heart_member_unlock">Heart member unlock</string> <string name="heart_member_unlock">Heart member unlock</string>
<string name="member_unlock">Member unlock</string> <string name="member_unlock">Member unlock</string>
<string name="release_to_send">Release to send</string>
<string name="my_chat_personal">My Chat Personal</string> <string name="my_chat_personal">My Chat Personal</string>
<string name="chat_setting">Chat Setting</string> <string name="chat_setting">Chat Setting</string>
<string name="auto_play_voice">Auto play voice</string> <string name="auto_play_voice">Auto play voice</string>
@ -466,6 +466,7 @@
<string name="hold_to_talk">Hold to Talk</string> <string name="hold_to_talk">Hold to Talk</string>
<string name="type_msg_hint">Type a message</string> <string name="type_msg_hint">Type a message</string>
<string name="swipe_up_to_cancel">Swipe Up to Cancel</string> <string name="swipe_up_to_cancel">Swipe Up to Cancel</string>
<string name="release_to_send">Release to Send</string>
<string name="release_to_cancel">Release to Cancel</string>
</resources> </resources>