fix: TTS播放按钮加到正确的页面(TaskListFragment)

TaskDetailFragment 未被使用,实际任务页面是 TaskListFragment。
- 在 TaskListFragment 布局加悬浮播放按钮
- 在 TaskListFragment 加 TTS 播放/停止逻辑
- 切换任务(左右滑动)时自动停止播报
- 离开页面自动停止播报

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
dongliang
2026-05-08 13:12:17 +09:30
parent aafae56826
commit bd6aa270c5
2 changed files with 80 additions and 0 deletions

View File

@@ -19,6 +19,7 @@ import com.xiaoqu.watch.databinding.FragmentTaskListBinding
import com.xiaoqu.watch.network.ApiResult
import com.xiaoqu.watch.network.api.TaskApi
import com.xiaoqu.watch.network.safeApiCall
import com.xiaoqu.watch.service.manager.EdgeTtsManager
import com.xiaoqu.watch.service.manager.NfcTaskManager
import com.xiaoqu.watch.ui.common.BaseFragment
import com.xiaoqu.watch.ui.widget.QuTipDialog
@@ -42,6 +43,7 @@ class TaskListFragment : BaseFragment<FragmentTaskListBinding>() {
@Inject lateinit var taskApi: TaskApi
@Inject lateinit var nfcTaskManager: NfcTaskManager
@Inject lateinit var edgeTtsManager: EdgeTtsManager
/** 任务 ID 列表queryTaskIds 返回) */
@@ -117,12 +119,17 @@ class TaskListFragment : BaseFragment<FragmentTaskListBinding>() {
false // 不拦截,让 ScrollView 继续处理滚动
}
// TTS 播放按钮
binding.btnTts.setOnClickListener { toggleTts() }
// 加载任务列表
fetchTaskIds()
}
override fun onDestroyView() {
stopVoice()
edgeTtsManager.stop()
edgeTtsManager.onComplete = null
super.onDestroyView()
}
@@ -237,6 +244,7 @@ class TaskListFragment : BaseFragment<FragmentTaskListBinding>() {
/** 下一个任务(左滑,内容从右滑入) */
private fun nextTask() {
if (taskIndex < taskList.size - 1) {
stopTts() // 切换任务时停止播报
taskIndex++
animateSwitch(fromRight = true)
}
@@ -245,6 +253,7 @@ class TaskListFragment : BaseFragment<FragmentTaskListBinding>() {
/** 上一个任务(右滑,内容从左滑入) */
private fun prevTask() {
if (taskIndex > 0) {
stopTts() // 切换任务时停止播报
taskIndex--
animateSwitch(fromRight = false)
}
@@ -1006,4 +1015,62 @@ class TaskListFragment : BaseFragment<FragmentTaskListBinding>() {
binding.btnAction.visibility = View.GONE
binding.tvTitle.text = statusTitle()
}
// ===== TTS 语音播报 =====
/** 切换播放/停止 */
private fun toggleTts() {
if (edgeTtsManager.isPlaying) {
stopTts()
} else {
startTts()
}
}
/** 开始播报当前任务内容 */
private fun startTts() {
val detail = currentDetail ?: return
// 拼接播报文本:有值的字段才读,空字段跳过
val parts = mutableListOf<String>()
if (detail.name.isNotBlank()) parts.add("任务:${detail.displayName}")
if (detail.positionText.isNotBlank()) parts.add("地点:${detail.positionText}")
if (detail.sendTime.isNotBlank()) parts.add("时间:${detail.sendTime}")
if (detail.point > 0) parts.add("积分:${detail.pointText}")
if (detail.content.isNotBlank()) parts.add("备注:${detail.content}")
if (parts.isEmpty()) return
val text = parts.joinToString("")
Timber.d("TTS 播报: $text")
// 更新按钮状态为播放中
updateTtsButton(playing = true)
// 播放完成回调:恢复按钮
edgeTtsManager.onComplete = {
activity?.runOnUiThread { updateTtsButton(playing = false) }
}
edgeTtsManager.speak(text) { errorMsg ->
Timber.w("TTS 播报失败: $errorMsg")
activity?.runOnUiThread { updateTtsButton(playing = false) }
}
}
/** 停止播报 */
private fun stopTts() {
edgeTtsManager.stop()
updateTtsButton(playing = false)
}
/** 更新 TTS 按钮的 UI 状态 */
private fun updateTtsButton(playing: Boolean) {
binding.btnTts.setImageResource(
if (playing) R.drawable.ic_speaker_stop else R.drawable.ic_speaker
)
binding.btnTts.setBackgroundResource(
if (playing) R.drawable.bg_tts_button_active else R.drawable.bg_tts_button
)
}
}

View File

@@ -364,6 +364,19 @@
</LinearLayout>
</ScrollView>
<!-- TTS 语音播报悬浮按钮:右侧垂直居中 -->
<ImageView
android:id="@+id/btnTts"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_gravity="center_vertical|end"
android:layout_marginEnd="4dp"
android:padding="6dp"
android:src="@drawable/ic_speaker"
android:background="@drawable/bg_tts_button"
android:contentDescription="语音播报" />
</FrameLayout>
<!-- ===== 底部操作按钮(高度缩小,字体加大) ===== -->