From 103a91e7c1aac976a9d44b4ebe8c13a0f1318cef Mon Sep 17 00:00:00 2001 From: renhaoting <370797079@qq.com> Date: Mon, 27 Oct 2025 14:28:46 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BD=95=E9=9F=B3=E5=8F=96=E6=B6=88=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../remax/visualnovel/ui/chat/ChatActivity.kt | 54 ++++++++++++------- .../remax/visualnovel/ui/chat/InputPanel.kt | 8 ++- .../ui/chat/ui/HoldToTalkDialog.kt | 52 ++++++++---------- .../app/src/main/res/values/strings.xml | 5 +- 4 files changed, 66 insertions(+), 53 deletions(-) diff --git a/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/ChatActivity.kt b/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/ChatActivity.kt index c34228b..78a832e 100644 --- a/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/ChatActivity.kt +++ b/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/ChatActivity.kt @@ -1,6 +1,7 @@ package com.remax.visualnovel.ui.chat +import android.graphics.Point import androidx.activity.viewModels import androidx.lifecycle.Observer 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.ui.chat.setting.model.ChatModelDialog import com.remax.visualnovel.ui.chat.ui.HoldToTalkDialog -import com.remax.visualnovel.ui.wallet.manager.WalletManager import com.remax.visualnovel.utils.RecordHelper import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.Job @@ -90,14 +90,21 @@ class ChatActivity : BaseBindingActivity() { private fun initInputPanelEvents() { with(binding.inputPanel) { - holdToTalk({ - mRecordAssist.startRecording() - }) { - mRecordAssist.stopTalk() - } + holdToTalk( + { + mRecordAssist.startRecording() + }, + { + mRecordAssist.stopTalk() + }, + touchPosCallback = { point -> + mRecordAssist.onTouchPointChanged(point) + } + ) } } + /** * 检查麦克风权限 */ @@ -179,6 +186,7 @@ class ChatActivity : BaseBindingActivity() { inner class RecordAssist { + private var mIsCancelled = false private var recordJob: Job? = null private val recordHelper by lazy { @@ -210,8 +218,8 @@ class ChatActivity : BaseBindingActivity() { private fun startTalk() { val maxTalkTime = 60 val minTalkTime = 1 - var recordingProgress = 0 + mIsCancelled = false holdToTalkDialog.show() recordHelper.startRecording(this@ChatActivity, { @@ -223,33 +231,41 @@ class ChatActivity : BaseBindingActivity() { }) }, { - if (recordingProgress >= minTalkTime) { - Timber.i("startRecording onStop: ${recordHelper.getFilename()}") + if (!mIsCancelled) { + if (recordingProgress >= minTalkTime) { + Timber.i("startRecording onStop: ${recordHelper.getFilename()}") - launchAndLoadingCollect({ - chatViewModel.voiceASR(recordHelper.getFilename()) - }) { - onSuccess = { - if (!it?.content.isNullOrBlank()) { - chatViewModel.sendMsg(it.content, errorCallback = sendMsgErrorCallback) + launchAndLoadingCollect({ + chatViewModel.voiceASR(recordHelper.getFilename()) + }) { + onSuccess = { + if (!it?.content.isNullOrBlank()) { + chatViewModel.sendMsg(it.content, errorCallback = sendMsgErrorCallback) + } } } - } - } else { - //录音最少1秒 - showToast(R.string.min_voice_time) + } else { + showToast(R.string.min_voice_time) //录音最少1秒 + } } }) } fun stopTalk() { + mIsCancelled = holdToTalkDialog.isTouchInCancelArea; holdToTalkDialog.dismiss() recordJob?.cancel() recordHelper.stopRecording() } + fun onTouchPointChanged(point: Point) { + if (holdToTalkDialog.isShowing) { + holdToTalkDialog.onTouchPointChanged(point) + } + } + } } \ No newline at end of file diff --git a/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/InputPanel.kt b/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/InputPanel.kt index c3c7624..50dce26 100644 --- a/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/InputPanel.kt +++ b/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/InputPanel.kt @@ -2,6 +2,7 @@ package com.remax.visualnovel.ui.chat import android.annotation.SuppressLint import android.content.Context +import android.graphics.Point import android.util.AttributeSet import android.view.MotionEvent import android.widget.FrameLayout @@ -82,7 +83,7 @@ class InputPanel @JvmOverloads constructor(context: Context, attrs: AttributeSet @SuppressLint("ClickableViewAccessibility") - fun holdToTalk(callback: () -> Unit, cancelCallback: () -> Unit) { + fun holdToTalk(callback: () -> Unit, cancelCallback: () -> Unit, touchPosCallback: (point: Point) -> Unit) { binding.ivHold2talk.run { setOnTouchListener { v, event -> when (event.action) { @@ -93,10 +94,15 @@ class InputPanel @JvmOverloads constructor(context: Context, attrs: AttributeSet MotionEvent.ACTION_UP -> { cancelCallback.invoke() } + + MotionEvent.ACTION_MOVE -> { + touchPosCallback.invoke(Point(event.rawX.toInt(), event.rawY.toInt())) + } } true } } } + } \ No newline at end of file diff --git a/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/ui/HoldToTalkDialog.kt b/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/ui/HoldToTalkDialog.kt index d809cd4..334fdcc 100644 --- a/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/ui/HoldToTalkDialog.kt +++ b/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/ui/HoldToTalkDialog.kt @@ -1,68 +1,58 @@ package com.remax.visualnovel.ui.chat.ui import android.content.Context +import android.graphics.Point import android.graphics.Rect -import android.view.MotionEvent -import android.view.View -import androidx.annotation.VisibleForTesting import androidx.core.view.isVisible import com.remax.visualnovel.R import com.remax.visualnovel.databinding.DialogHoldToTalkBinding import com.remax.visualnovel.widget.dialoglib.LBindingDialog -/** - * Created by HJW on 2025/8/16 - */ + class HoldToTalkDialog(context: Context) : LBindingDialog(context, DialogHoldToTalkBinding::inflate) { + var isTouchInCancelArea = false + fun build(): HoldToTalkDialog { with() setBottom() setBgColorToken(R.string.color_transparent) setMaskValue(0f) - initRootTouchEvent() show() 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 { - val rect = Rect() - binding.viewRelease.getHitRect(rect) - return rect.contains(event.rawX.toInt(), event.rawY.toInt()) - } - - private fun updateStateUI(event: MotionEvent) { + fun onTouchPointChanged(point: Point) { with (binding) { - when (isInValidArea(event)) { - true -> { + isTouchInCancelArea = !getTouchValidArea().contains(point.x, point.y) + when (isTouchInCancelArea) { + false -> { viewRelease.setBackgroundResource(R.mipmap.bg_recording_normal) cancelHintRoot.isVisible = true + tvRelease.text = context.resources.getString(R.string.release_to_send) } - false -> { + true -> { viewRelease.setBackgroundResource(R.mipmap.bg_recording_cancel) 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 + ) + } } diff --git a/VisualNovel/app/src/main/res/values/strings.xml b/VisualNovel/app/src/main/res/values/strings.xml index 756a874..c789ab3 100644 --- a/VisualNovel/app/src/main/res/values/strings.xml +++ b/VisualNovel/app/src/main/res/values/strings.xml @@ -337,7 +337,7 @@ Prompt Heart member unlock Member unlock - Release to send + My Chat Personal Chat Setting Auto play voice @@ -466,6 +466,7 @@ Hold to Talk Type a message Swipe Up to Cancel - + Release to Send + Release to Cancel \ No newline at end of file