refactor(task): 重构复合材料铺贴任务流程

- 将任务列表注释更新为包含决策中心功能
- 移除不必要的导入和枚举定义,简化 CompositeLayupTaskActivity 类结构
- 替换基础 Activity 为 BaseListFormLayoutNormalActivity 以支持分页功能
- 更新适配器实现为 BasePagedAdapter 和 CommonPagedAdapter
- 简化屏幕模式管理,移除复杂的 UI 状态切换逻辑
- 优化拍照和识别流程,直接跳转到结果页面
- 添加 CompositeLayupResultActivity 来处理识别结果和铺贴过程
- 更新视图模型继承自 BaseListViewModel 并优化数据加载逻辑
- 修改布局文件以匹配新的 UI 流程设计
- 在 AndroidManifest 中注册新的结果活动页面
这个提交包含在:
徐勤民 2026-04-22 18:14:53 +08:00
父节点 47fa2c4464
当前提交 089c807340
共有 10 个文件被更改,包括 596 次插入555 次删除

查看文件

@ -56,7 +56,7 @@ android {
buildConfigField("String", "API_COOKIE", "\"__itrace_wid=87125211-8742-4f12-b5ca-32b9b6c860e4; locale=zh-Hans; _webtracing_device_id=t_13501877-b9b303fc-d3f52eb530e026b0\"") buildConfigField("String", "API_COOKIE", "\"__itrace_wid=87125211-8742-4f12-b5ca-32b9b6c860e4; locale=zh-Hans; _webtracing_device_id=t_13501877-b9b303fc-d3f52eb530e026b0\"")
buildConfigField("String", "API_ENVIRONMENT", "\"2\"") buildConfigField("String", "API_ENVIRONMENT", "\"2\"")
buildConfigField("String", "API_CURRENT_USER_ID", "\"rokid\"") buildConfigField("String", "API_CURRENT_USER_ID", "\"rokid\"")
// ++fo // ++fo+
buildConfigField("String", "API_BASE_URL_1", "\"http://10.230.4.80:12119\"") buildConfigField("String", "API_BASE_URL_1", "\"http://10.230.4.80:12119\"")
// //
buildConfigField("String", "API_BASE_URL_2", "\"http://10.230.4.80\"") buildConfigField("String", "API_BASE_URL_2", "\"http://10.230.4.80\"")

查看文件

@ -78,6 +78,9 @@
<activity <activity
android:name=".ui.CompositeLayupTaskActivity" android:name=".ui.CompositeLayupTaskActivity"
android:exported="false" /> android:exported="false" />
<activity
android:name=".ui.CompositeLayupResultActivity"
android:exported="false" />
<activity <activity
android:name=".ui.ChatActivity" android:name=".ui.ChatActivity"
android:exported="false" /> android:exported="false" />

查看文件

@ -0,0 +1,319 @@
package com.nova.brain.glass.ui
import android.content.Intent
import android.os.Environment
import android.os.Handler
import android.os.Looper
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.nova.brain.glass.R
import com.nova.brain.glass.databinding.ActivityCompositeLayupResultBinding
import com.nova.brain.glass.helper.GlassMediaServiceHelper
import com.nova.brain.glass.helper.OfflineCmdListener
import com.nova.brain.glass.helper.OfflineCmdServiceHelper
import com.nova.brain.glass.model.ItemItem
import com.nova.brain.glass.viewmodel.CompositeLayupResultState
import com.nova.brain.glass.viewmodel.CompositeLayupResultVM
import com.rokid.security.glass3.sdk.base.data.media.PhotoResolution
import com.rokid.security.system.server.media.callback.PhotoFileCallback
import com.xuqm.base.adapter.CommonAdapter
import com.xuqm.base.adapter.ViewHolder
import com.xuqm.base.extensions.showMessage
import com.xuqm.base.ui.BaseActivity
import java.io.File
import java.util.UUID
class CompositeLayupResultActivity : BaseActivity<ActivityCompositeLayupResultBinding>() {
override fun getLayoutId(): Int = R.layout.activity_composite_layup_result
override fun fullscreen(): Boolean = true
private val viewModel: CompositeLayupResultVM by lazy {
ViewModelProvider(this)[CompositeLayupResultVM::class.java]
}
private enum class UiMode {
RECOGNIZE_SUCCESS,
RECOGNIZE_FAILED,
LAYUP_PROMPT,
LAYUP_WORKING,
CONFIRM_FINISH,
COMPLETE
}
private val taskNo: String by lazy { intent.getStringExtra(EXTRA_TASK_NO).orEmpty() }
private val taskName: String by lazy { intent.getStringExtra(EXTRA_TASK_NAME).orEmpty() }
private val partNo: String by lazy { intent.getStringExtra(EXTRA_PART_NO).orEmpty() }
private val photoPath: String by lazy { intent.getStringExtra(EXTRA_PHOTO_PATH).orEmpty() }
private val stepSeq: Int by lazy { intent.getIntExtra(EXTRA_STEP_SEQ, 1) }
private val totalSteps: Int by lazy { intent.getIntExtra(EXTRA_TOTAL_STEPS, 1) }
private val direction: String by lazy { intent.getStringExtra(EXTRA_DIRECTION).orEmpty() }
private val vacuum: String by lazy { intent.getStringExtra(EXTRA_VACUUM).orEmpty() }
private val uiHandler = Handler(Looper.getMainLooper())
private var isPhoto = false
private var uiMode = UiMode.RECOGNIZE_SUCCESS
private val layupWorkingRunnable: Runnable = Runnable {
if (uiMode == UiMode.LAYUP_PROMPT) {
applyMode(UiMode.LAYUP_WORKING)
}
}
private val completeRunnable: Runnable = Runnable {
if (uiMode == UiMode.COMPLETE) {
goTaskList()
}
}
private val listener: OfflineCmdListener = object : OfflineCmdListener {
override fun onOfflineCmd(cmd: String) {
runOnUiThread {
when (cmd) {
"退出", "返回", "退回" -> finish()
"重拍", "重新拍照", "重新拍摄" -> if (uiMode == UiMode.RECOGNIZE_FAILED) retake()
"开始铺贴" -> if (uiMode == UiMode.RECOGNIZE_SUCCESS) startLayup()
"确认并继续", "继续" -> if (uiMode == UiMode.CONFIRM_FINISH) confirmAndContinue()
"" -> if (uiMode == UiMode.CONFIRM_FINISH) applyMode(UiMode.LAYUP_WORKING)
"完成", "完成任务" -> if (uiMode == UiMode.CONFIRM_FINISH && stepSeq >= totalSteps) finishCurrentTask()
"返回任务列表" -> if (uiMode == UiMode.COMPLETE) goTaskList()
}
}
}
}
private val photoCallbackId = UUID.randomUUID().toString()
private val photoCallback: PhotoFileCallback = object : PhotoFileCallback.Stub() {
override fun onTakePhoto(path: String) = Unit
override fun getCallbackId(): String = photoCallbackId
override fun onTakePhotoV2(path: String?, width: Int, height: Int) {
if (path == null) {
if (isPhoto) {
isPhoto = false
takePhoto()
} else {
binding.hint.text = "单击或语音输入“重新拍照”,进入下一步"
"相机异常".showMessage()
}
return
}
startActivity(Intent(this@CompositeLayupResultActivity, CompositeLayupResultActivity::class.java).apply {
putExtra(EXTRA_PHOTO_PATH, path)
putExtra(EXTRA_TASK_NO, taskNo)
putExtra(EXTRA_TASK_NAME, taskName)
putExtra(EXTRA_PART_NO, partNo)
putExtra(EXTRA_STEP_SEQ, stepSeq)
putExtra(EXTRA_TOTAL_STEPS, totalSteps)
putExtra(EXTRA_DIRECTION, direction)
putExtra(EXTRA_VACUUM, vacuum)
})
finish()
}
}
override fun initData() {
super.initData()
window.addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
binding.baseRecyclerView.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
binding.baseRecyclerView.adapter = actionAdapter
binding.main.setOnClickListener {
if (uiMode == UiMode.LAYUP_WORKING) {
applyMode(UiMode.CONFIRM_FINISH)
}
}
viewModel.resultState.observe(this) { state ->
when (state) {
CompositeLayupResultState.LOADING -> {
binding.hint.text = "OCR识别中,请稍后..."
renderActions(emptyList())
}
CompositeLayupResultState.SUCCESS -> {
val result = viewModel.recognizeResult.value ?: return@observe
if (result.success) {
applyMode(UiMode.RECOGNIZE_SUCCESS)
} else {
applyMode(UiMode.RECOGNIZE_FAILED, result.errorMessage.ifBlank { "识别失败,请重试!" })
}
}
CompositeLayupResultState.FAILED -> {
applyMode(UiMode.RECOGNIZE_FAILED, viewModel.errorMessage.value ?: "识别失败,请重试!")
}
else -> Unit
}
}
if (taskNo.isNotBlank() && photoPath.isNotBlank()) {
viewModel.recognize(taskNo, stepSeq, photoPath)
}
}
private fun applyMode(mode: UiMode, errorMessage: String = "") {
uiMode = mode
uiHandler.removeCallbacks(layupWorkingRunnable)
uiHandler.removeCallbacks(completeRunnable)
binding.icon.visibility = android.view.View.VISIBLE
when (mode) {
UiMode.RECOGNIZE_SUCCESS -> {
binding.icon.setImageResource(R.mipmap.ocr_true)
binding.title.text = "铺贴层与零件信息正确"
binding.subtitle1.text = "识别到这是${stepSeq}/${totalSteps}"
binding.subtitle2.text = buildInstruction()
renderActions(listOf("开始铺贴"))
binding.hint.text = "单击或语音输入“开始铺贴”,进入下一步"
}
UiMode.RECOGNIZE_FAILED -> {
binding.icon.setImageResource(R.mipmap.ocr_false)
binding.title.text = errorMessage
binding.subtitle1.text = "识别到这是${stepSeq}/${totalSteps}"
binding.subtitle2.text = "请重新拿取"
renderActions(listOf("重新拍照"))
binding.hint.text = "单击或语音输入“重新拍照”,进入下一步"
}
UiMode.LAYUP_PROMPT -> {
binding.icon.visibility = android.view.View.INVISIBLE
binding.title.text = "请进行铺贴工作"
binding.subtitle1.text = "完成后,滑动唤醒眼镜!"
binding.subtitle2.text = ""
renderActions(emptyList())
binding.hint.text = ""
uiHandler.postDelayed(layupWorkingRunnable, 5000L)
}
UiMode.LAYUP_WORKING -> {
binding.icon.visibility = android.view.View.INVISIBLE
binding.title.text = "正在铺贴第${stepSeq}"
binding.subtitle1.text = buildWorkingInstruction()
binding.subtitle2.text = ""
renderActions(emptyList())
binding.hint.text = ""
}
UiMode.CONFIRM_FINISH -> {
binding.icon.visibility = android.view.View.INVISIBLE
binding.title.text = "请确认是否已完成第${stepSeq}/${totalSteps}张铺贴"
binding.subtitle1.text = ""
binding.subtitle2.text = ""
renderActions(listOf(if (stepSeq >= totalSteps) "完成" else "确认并继续", ""))
binding.hint.text = "点击或语音输入对应按钮,继续流程"
}
UiMode.COMPLETE -> {
binding.icon.setImageResource(R.mipmap.ocr_true)
binding.title.text = "恭喜完成当前铺贴任务!"
binding.subtitle1.text = "3S后自动返回铺贴任务界面"
binding.subtitle2.text = ""
renderActions(listOf("返回任务列表"))
binding.hint.text = ""
uiHandler.postDelayed(completeRunnable, 3000L)
}
}
}
private fun buildInstruction(): String {
val vacuumText = if (vacuum.isBlank()) "" else "请真空铺贴、"
val directionText = if (direction.isBlank()) "" else "纹理方向:$direction"
return (vacuumText + directionText).ifBlank { "请开始铺贴" }
}
private fun buildWorkingInstruction(): String {
val vacuumText = if (vacuum.isBlank()) "" else "请真空铺贴、"
val directionText = if (direction.isBlank()) "" else "纹理方向$direction"
return "${vacuumText}${directionText}撕衬纸\n完成后,滑动唤醒眼镜!"
}
private fun renderActions(actions: List<String>) {
actionAdapter.setmDatas(actions.map(::ItemItem))
binding.baseRecyclerView.visibility = if (actions.isEmpty()) android.view.View.INVISIBLE else android.view.View.VISIBLE
binding.baseRecyclerView.layoutParams = binding.baseRecyclerView.layoutParams.apply {
height = dpToPx(if (actions.size > 1) 152 else 88)
}
}
private fun startLayup() {
applyMode(UiMode.LAYUP_PROMPT)
}
private fun retake() {
binding.hint.text = "拍照中,请稍后..."
isPhoto = true
takePhoto()
}
private fun takePhoto() {
val fileName = "composite_layup_${System.currentTimeMillis()}.png"
val file = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
fileName
)
GlassMediaServiceHelper.takePhoto(PhotoResolution.RESOLUTION_720P, file.absolutePath)
}
private fun confirmAndContinue() {
startActivity(Intent(this, CompositeLayupTaskActivity::class.java).apply {
putExtra(CompositeLayupTaskActivity.EXTRA_TASK_NO, taskNo)
putExtra(CompositeLayupTaskActivity.EXTRA_STEP_SEQ, stepSeq + 1)
})
finish()
}
private fun finishCurrentTask() {
applyMode(UiMode.COMPLETE)
}
private fun goTaskList() {
startActivity(Intent(this, TaskListActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
})
finish()
}
private fun dpToPx(dp: Int): Int =
(dp * resources.displayMetrics.density).toInt()
override fun onResume() {
super.onResume()
GlassMediaServiceHelper.addPhotoCallback(photoCallback)
OfflineCmdServiceHelper.addListenerCompositeLayup()
OfflineCmdServiceHelper.addOnLineListener(listener)
}
override fun onPause() {
super.onPause()
uiHandler.removeCallbacks(layupWorkingRunnable)
uiHandler.removeCallbacks(completeRunnable)
GlassMediaServiceHelper.removePhotoCallback(photoCallback)
OfflineCmdServiceHelper.removeListenerCompositeLayup()
OfflineCmdServiceHelper.removeOnLineListener(listener)
}
override fun onDestroy() {
super.onDestroy()
window.clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
private val actionAdapter: CommonAdapter<ItemItem> =
object : CommonAdapter<ItemItem>(R.layout.item_manual_result_action) {
override fun convert(holder: ViewHolder, item: ItemItem, position: Int) {
holder.setText(R.id.text, item.text)
.setClickListener(R.id.actionRoot) {
when (item.text) {
"重新拍照" -> retake()
"开始铺贴" -> startLayup()
"确认并继续" -> confirmAndContinue()
"" -> applyMode(UiMode.LAYUP_WORKING)
"完成" -> finishCurrentTask()
"返回任务列表" -> goTaskList()
}
}
}
}
companion object {
const val EXTRA_PHOTO_PATH = "extra_photo_path"
const val EXTRA_TASK_NO = "extra_task_no"
const val EXTRA_TASK_NAME = "extra_task_name"
const val EXTRA_PART_NO = "extra_part_no"
const val EXTRA_STEP_SEQ = "extra_step_seq"
const val EXTRA_TOTAL_STEPS = "extra_total_steps"
const val EXTRA_DIRECTION = "extra_direction"
const val EXTRA_VACUUM = "extra_vacuum"
}
}

查看文件

@ -2,11 +2,6 @@ package com.nova.brain.glass.ui
import android.content.Intent import android.content.Intent
import android.os.Environment import android.os.Environment
import android.os.Handler
import android.os.Looper
import android.view.View
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.nova.brain.glass.R import com.nova.brain.glass.R
import com.nova.brain.glass.databinding.ActivityCompositeLayupTaskBinding import com.nova.brain.glass.databinding.ActivityCompositeLayupTaskBinding
@ -14,84 +9,49 @@ import com.nova.brain.glass.helper.GlassMediaServiceHelper
import com.nova.brain.glass.helper.OfflineCmdListener import com.nova.brain.glass.helper.OfflineCmdListener
import com.nova.brain.glass.helper.OfflineCmdServiceHelper import com.nova.brain.glass.helper.OfflineCmdServiceHelper
import com.nova.brain.glass.model.ItemItem import com.nova.brain.glass.model.ItemItem
import com.nova.brain.glass.viewmodel.CompositeLayupRecognizeState
import com.nova.brain.glass.viewmodel.CompositeLayupTaskVM import com.nova.brain.glass.viewmodel.CompositeLayupTaskVM
import com.rokid.security.glass3.sdk.base.data.media.PhotoResolution import com.rokid.security.glass3.sdk.base.data.media.PhotoResolution
import com.rokid.security.system.server.media.callback.PhotoFileCallback import com.rokid.security.system.server.media.callback.PhotoFileCallback
import com.xuqm.base.adapter.CommonAdapter import com.xuqm.base.adapter.BasePagedAdapter
import com.xuqm.base.adapter.CommonPagedAdapter
import com.xuqm.base.adapter.ViewHolder import com.xuqm.base.adapter.ViewHolder
import com.xuqm.base.common.LogHelper import com.xuqm.base.common.LogHelper
import com.xuqm.base.extensions.showMessage import com.xuqm.base.extensions.showMessage
import com.xuqm.base.ui.BaseActivity import com.xuqm.base.ui.BaseListFormLayoutNormalActivity
import java.io.File import java.io.File
import java.util.UUID import java.util.UUID
class CompositeLayupTaskActivity : BaseActivity<ActivityCompositeLayupTaskBinding>() { class CompositeLayupTaskActivity :
BaseListFormLayoutNormalActivity<ItemItem, CompositeLayupTaskVM, ActivityCompositeLayupTaskBinding>() {
override fun getLayoutId(): Int = R.layout.activity_composite_layup_task override fun getLayoutId(): Int = R.layout.activity_composite_layup_task
override fun fullscreen(): Boolean = true override fun fullscreen(): Boolean = true
override fun getRecyclerOrientation(): Int = RecyclerView.VERTICAL
private enum class ScreenMode {
TASK_INFO,
CAPTURE,
RECOGNIZE_SUCCESS,
RECOGNIZE_FAILED,
LAYUP_PROMPT,
LAYUP_WORKING,
CONFIRM_FINISH,
COMPLETE
}
private val viewModel: CompositeLayupTaskVM by lazy {
ViewModelProvider(this)[CompositeLayupTaskVM::class.java]
}
private val taskNoFromIntent: String by lazy { private val taskNoFromIntent: String by lazy {
intent.getStringExtra(EXTRA_TASK_NO).orEmpty() intent.getStringExtra(EXTRA_TASK_NO).orEmpty()
} }
private val mainHandler = Handler(Looper.getMainLooper()) private val stepSeqFromIntent: Int by lazy {
intent.getIntExtra(EXTRA_STEP_SEQ, 0)
}
private var isPhotoFallback = false private var isPhoto = false
private var isCaptureInFlight = false private var isCaptureInFlight = false
private var screenMode = ScreenMode.TASK_INFO private var hasNavigatedNextPage = false
private var autoReturned = false
private val layupWorkingRunnable = Runnable { private val listener: OfflineCmdListener = object : OfflineCmdListener {
if (screenMode == ScreenMode.LAYUP_PROMPT) {
applyScreenMode(ScreenMode.LAYUP_WORKING)
}
}
private val completeRunnable = Runnable {
if (screenMode == ScreenMode.COMPLETE && !autoReturned) {
autoReturned = true
goTaskList()
}
}
private val listener = object : OfflineCmdListener {
override fun onOfflineCmd(cmd: String) { override fun onOfflineCmd(cmd: String) {
runOnUiThread { runOnUiThread {
when (cmd) { when (cmd) {
"退出", "返回", "退回" -> finish() "退出", "返回", "退回" -> finish()
"开始", "开始任务" -> if (screenMode == ScreenMode.TASK_INFO) startCaptureFlow() "开始", "拍照", "开始拍照", "开始任务" -> startCapture()
"重新拍照", "重拍", "重新拍摄" -> {
if (screenMode == ScreenMode.RECOGNIZE_FAILED) startCaptureFlow()
}
"开始铺贴" -> if (screenMode == ScreenMode.RECOGNIZE_SUCCESS) startLayup()
"确认并继续", "继续" -> if (screenMode == ScreenMode.CONFIRM_FINISH) confirmAndContinue()
"" -> if (screenMode == ScreenMode.CONFIRM_FINISH) backToWorking()
"完成", "完成任务" -> {
if (screenMode == ScreenMode.CONFIRM_FINISH && viewModel.canFinishAfterCurrentStep()) {
finishCurrentTask()
}
}
"返回任务列表" -> if (screenMode == ScreenMode.COMPLETE) goTaskList()
} }
} }
} }
} }
private val photoCallbackId = UUID.randomUUID().toString() private val photoCallbackId = UUID.randomUUID().toString()
private val photoCallback = object : PhotoFileCallback.Stub() { private val photoCallback: PhotoFileCallback = object : PhotoFileCallback.Stub() {
override fun onTakePhoto(path: String) { override fun onTakePhoto(path: String) {
LogHelper.d("CompositeLayupTask onTakePhoto: $path") LogHelper.d("CompositeLayupTask onTakePhoto: $path")
} }
@ -101,293 +61,128 @@ class CompositeLayupTaskActivity : BaseActivity<ActivityCompositeLayupTaskBindin
override fun onTakePhotoV2(path: String?, width: Int, height: Int) { override fun onTakePhotoV2(path: String?, width: Int, height: Int) {
LogHelper.d("CompositeLayupTask onTakePhotoV2 width=$width height=$height path=$path") LogHelper.d("CompositeLayupTask onTakePhotoV2 width=$width height=$height path=$path")
if (path == null) { if (path == null) {
if (isPhotoFallback) { if (isPhoto) {
isPhotoFallback = false isPhoto = false
takePhoto() takePhoto()
} else { } else {
isCaptureInFlight = false isCaptureInFlight = false
runOnUiThread { runOnUiThread {
val message = "相机异常,请重试" binding.hint.text = "单击或语音输入“开始”,进入下一步"
updateHint(message)
applyScreenMode(ScreenMode.RECOGNIZE_FAILED, message)
} }
"相机异常".showMessage() "相机异常".showMessage()
} }
return return
} }
if (hasNavigatedNextPage) {
return
}
val taskDetail = viewModel.taskDetail.value
val currentDetail = viewModel.currentDetail()
val currentTaskStepSeq = currentDetail?.stepSeq ?: viewModel.currentStepSeq
isCaptureInFlight = false isCaptureInFlight = false
runOnUiThread { hasNavigatedNextPage = true
updateHint("OCR识别中,请稍后...") GlassMediaServiceHelper.removePhotoCallback(photoCallback)
viewModel.recognize(path) OfflineCmdServiceHelper.removeListenerCompositeLayup()
} OfflineCmdServiceHelper.removeOnLineListener(listener)
} startActivity(Intent(this@CompositeLayupTaskActivity, CompositeLayupResultActivity::class.java).apply {
} putExtra(CompositeLayupResultActivity.EXTRA_PHOTO_PATH, path)
putExtra(CompositeLayupResultActivity.EXTRA_TASK_NO, viewModel.taskNo)
private val actionAdapter = object : CommonAdapter<ItemItem>(R.layout.item_manual_result_action) { putExtra(CompositeLayupResultActivity.EXTRA_TASK_NAME, taskDetail?.taskName.orEmpty())
override fun convert(holder: ViewHolder, item: ItemItem, position: Int) { putExtra(CompositeLayupResultActivity.EXTRA_PART_NO, taskDetail?.partNo.orEmpty())
holder.setText(R.id.text, item.text) putExtra(CompositeLayupResultActivity.EXTRA_STEP_SEQ, currentTaskStepSeq)
.setClickListener(R.id.actionRoot) { putExtra(CompositeLayupResultActivity.EXTRA_TOTAL_STEPS, viewModel.totalSteps)
when (item.text) { putExtra(CompositeLayupResultActivity.EXTRA_DIRECTION, currentDetail?.direction.orEmpty())
"开始任务" -> startCaptureFlow() putExtra(CompositeLayupResultActivity.EXTRA_VACUUM, currentDetail?.vacuum.orEmpty())
"重新拍照" -> startCaptureFlow() })
"开始铺贴" -> startLayup() finish()
"确认并继续" -> confirmAndContinue()
"" -> backToWorking()
"完成" -> finishCurrentTask()
"返回任务列表" -> goTaskList()
}
}
} }
} }
override fun initData() { override fun initData() {
super.initData() super.initData()
window.addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) window.addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
binding.baseRecyclerView.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false) binding.tvTaskHeader.text = "复材铺贴任务"
binding.baseRecyclerView.adapter = actionAdapter
binding.main.setOnClickListener {
if (screenMode == ScreenMode.LAYUP_WORKING) {
applyScreenMode(ScreenMode.CONFIRM_FINISH)
}
}
observeViewModel()
applyScreenMode(ScreenMode.TASK_INFO)
if (taskNoFromIntent.isBlank()) {
val message = "任务编号缺失"
updateHint(message)
message.showMessage()
} else {
viewModel.loadTaskDetail(taskNoFromIntent)
}
}
private fun observeViewModel() {
viewModel.taskDetail.observe(this) { detail -> viewModel.taskDetail.observe(this) { detail ->
if (detail != null) { if (detail == null) return@observe
binding.tvTaskName.text = detail.taskName.ifBlank { "铺贴任务" } val currentDetail = viewModel.currentDetail()
renderTaskInfo() binding.tvTaskName.text = currentDetail?.ply?.ifBlank {
applyScreenMode(ScreenMode.TASK_INFO) detail.taskName.ifBlank { "铺贴任务" }
} } ?: detail.taskName.ifBlank { "铺贴任务" }
}
viewModel.taskDetailError.observe(this) { msg ->
if (msg.isNotBlank()) {
updateHint(msg)
msg.showMessage()
}
}
viewModel.recognizeState.observe(this) { state ->
when (state) {
CompositeLayupRecognizeState.LOADING -> {
updateHint("OCR识别中,请稍后...")
renderActions(emptyList())
}
CompositeLayupRecognizeState.SUCCESS -> handleRecognizeResult()
CompositeLayupRecognizeState.FAILED -> {
val error = viewModel.recognizeError.value?.ifBlank { "OCR识别失败" } ?: "OCR识别失败"
applyScreenMode(ScreenMode.RECOGNIZE_FAILED, error)
}
else -> Unit
}
}
}
private fun renderTaskInfo() {
val detail = viewModel.taskDetail.value ?: return
binding.content1.text = "零件号:${detail.partNo.ifBlank { "-" }}" binding.content1.text = "零件号:${detail.partNo.ifBlank { "-" }}"
binding.content2.text = "任务编号:${detail.taskNo.ifBlank { taskNoFromIntent }}" binding.content2.text = "任务编号:${detail.taskNo.ifBlank { taskNoFromIntent }}"
binding.content3.text = "任务进度:${viewModel.currentProgressText()}" binding.content3.text = "任务进度:${viewModel.currentStepSeq}/${detail.taskSteps}"
binding.hint.text = "单击或语音输入“开始”,进入下一步"
} }
viewModel.taskDetailError.observe(this) { message ->
private fun handleRecognizeResult() { if (message.isNotBlank()) {
val result = viewModel.recognizeResult.value ?: return binding.hint.text = "单击或语音输入“开始”,进入下一步"
if (result.success) { message.showMessage()
applyScreenMode(ScreenMode.RECOGNIZE_SUCCESS) }
}
if (taskNoFromIntent.isBlank()) {
binding.hint.text = "任务编号缺失"
} else { } else {
applyScreenMode( viewModel.loadTaskDetail(taskNoFromIntent, stepSeqFromIntent.takeIf { it > 0 })
ScreenMode.RECOGNIZE_FAILED,
result.errorMessage.ifBlank { "识别失败,请重试!" }
)
}
viewModel.resetRecognizeState()
}
private fun startCaptureFlow() {
if (isCaptureInFlight || taskNoFromIntent.isBlank()) {
return
}
isCaptureInFlight = true
applyScreenMode(ScreenMode.CAPTURE)
takePhoto()
}
private fun takePhoto() {
isPhotoFallback = true
val fileName = "composite_layup_${System.currentTimeMillis()}.png"
val file = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
fileName
)
GlassMediaServiceHelper.takePhoto(PhotoResolution.RESOLUTION_720P, file.absolutePath)
}
private fun startLayup() {
applyScreenMode(ScreenMode.LAYUP_PROMPT)
}
private fun backToWorking() {
applyScreenMode(ScreenMode.LAYUP_WORKING)
}
private fun confirmAndContinue() {
if (viewModel.canFinishAfterCurrentStep()) {
finishCurrentTask()
return
}
if (viewModel.moveToNextStep()) {
renderTaskInfo()
applyScreenMode(ScreenMode.TASK_INFO)
} }
} }
private fun finishCurrentTask() {
applyScreenMode(ScreenMode.COMPLETE)
}
private fun applyScreenMode(mode: ScreenMode, errorMessage: String = "") {
screenMode = mode
mainHandler.removeCallbacks(layupWorkingRunnable)
mainHandler.removeCallbacks(completeRunnable)
renderTaskInfo()
binding.groupStart.visibility = if (mode == ScreenMode.TASK_INFO) View.VISIBLE else View.GONE
binding.groupCapture.visibility = if (mode == ScreenMode.CAPTURE) View.VISIBLE else View.GONE
binding.groupResult.visibility =
if (mode == ScreenMode.RECOGNIZE_SUCCESS || mode == ScreenMode.RECOGNIZE_FAILED) View.VISIBLE else View.GONE
binding.groupWork.visibility =
if (mode == ScreenMode.LAYUP_PROMPT || mode == ScreenMode.LAYUP_WORKING) View.VISIBLE else View.GONE
binding.groupConfirm.visibility = if (mode == ScreenMode.CONFIRM_FINISH) View.VISIBLE else View.GONE
binding.groupComplete.visibility = if (mode == ScreenMode.COMPLETE) View.VISIBLE else View.GONE
when (mode) {
ScreenMode.TASK_INFO -> {
binding.captureMessage.text = "请对准下一张复材铺贴物料上的字符内容"
binding.startIcon.setImageResource(R.mipmap.ocr_photo)
renderActions(listOf("开始任务"))
updateHint("单击或语音输入\"开始\",进入下一步")
}
ScreenMode.CAPTURE -> {
binding.captureMessage.text = "请对准复材铺贴物料上的字符内容"
renderActions(emptyList())
updateHint("拍照中,请稍后...")
}
ScreenMode.RECOGNIZE_SUCCESS -> {
val currentDetail = viewModel.currentDetail()
binding.resultIcon.setImageResource(R.mipmap.ocr_true)
binding.resultTitle.text = "铺贴层与零件信息正确"
binding.resultSubtitle1.text = "识别到这是${viewModel.currentProgressText()}"
binding.resultSubtitle2.text = buildRecognizeInstruction(currentDetail?.vacuum, currentDetail?.direction)
renderActions(listOf("开始铺贴"))
updateHint("单击或语音输入\"开始铺贴\",进入下一步")
}
ScreenMode.RECOGNIZE_FAILED -> {
binding.resultIcon.setImageResource(R.mipmap.ocr_false)
binding.resultTitle.text = errorMessage.ifBlank { "识别失败,请重试!" }
binding.resultSubtitle1.text = "识别到这是${viewModel.currentProgressText()}"
binding.resultSubtitle2.text = "请重新拿取"
renderActions(listOf("重新拍照"))
updateHint("单击或语音输入\"重新拍照\",进入下一步")
}
ScreenMode.LAYUP_PROMPT -> {
binding.workText.text = "请进行铺贴工作\n完成后,滑动唤醒眼镜!"
renderActions(emptyList())
updateHint("")
mainHandler.postDelayed(layupWorkingRunnable, 5000L)
}
ScreenMode.LAYUP_WORKING -> {
binding.workText.text = buildWorkingInstruction()
renderActions(emptyList())
updateHint("")
}
ScreenMode.CONFIRM_FINISH -> {
binding.confirmTitle.text = "请确认是否已完成第${viewModel.currentProgressText()}张铺贴"
val primary = if (viewModel.canFinishAfterCurrentStep()) "完成" else "确认并继续"
renderActions(listOf(primary, ""))
updateHint("点击或语音输入对应按钮,继续流程")
}
ScreenMode.COMPLETE -> {
autoReturned = false
binding.completeSubtitle.text = "3S后自动返回铺贴任务界面"
renderActions(listOf("返回任务列表"))
updateHint("")
mainHandler.postDelayed(completeRunnable, 3000L)
}
}
}
private fun renderActions(actions: List<String>) {
actionAdapter.setmDatas(actions.map(::ItemItem))
binding.baseRecyclerView.layoutParams = binding.baseRecyclerView.layoutParams.apply {
height = dpToPx(
when {
actions.isEmpty() -> 88
actions.size == 1 -> 88
else -> 152
}
)
}
binding.baseRecyclerView.visibility = if (actions.isEmpty()) View.INVISIBLE else View.VISIBLE
}
private fun updateHint(text: String) {
binding.hint.text = text
binding.hint.visibility = if (text.isBlank()) View.INVISIBLE else View.VISIBLE
}
private fun buildRecognizeInstruction(vacuum: String?, direction: String?): String {
val vacuumText = if (vacuum.isNullOrBlank()) "" else "请真空铺贴、"
val directionText = if (direction.isNullOrBlank()) "" else "纹理方向$direction"
return (vacuumText + directionText).ifBlank { "请开始铺贴" }
}
private fun buildWorkingInstruction(): String {
val detail = viewModel.currentDetail()
val stepText = "正在铺贴第${viewModel.currentStepSeq}"
val vacuumText = if (detail?.vacuum.isNullOrBlank()) "" else "请真空铺贴、"
val directionText = if (detail?.direction.isNullOrBlank()) "" else "纹理方向${detail?.direction}"
return "$stepText\n${vacuumText}${directionText}撕衬纸\n完成后,滑动唤醒眼镜!"
}
private fun goTaskList() {
startActivity(Intent(this, TaskListActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
})
finish()
}
private fun dpToPx(dp: Int): Int =
(dp * resources.displayMetrics.density).toInt()
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
hasNavigatedNextPage = false
isCaptureInFlight = false
GlassMediaServiceHelper.addPhotoCallback(photoCallback) GlassMediaServiceHelper.addPhotoCallback(photoCallback)
OfflineCmdServiceHelper.addListenerCompositeLayup()
OfflineCmdServiceHelper.addOnLineListener(listener) OfflineCmdServiceHelper.addOnLineListener(listener)
OfflineCmdServiceHelper.addListenerCompositeLayup()
} }
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
mainHandler.removeCallbacks(layupWorkingRunnable)
mainHandler.removeCallbacks(completeRunnable)
GlassMediaServiceHelper.removePhotoCallback(photoCallback)
OfflineCmdServiceHelper.removeListenerCompositeLayup() OfflineCmdServiceHelper.removeListenerCompositeLayup()
OfflineCmdServiceHelper.removeOnLineListener(listener) OfflineCmdServiceHelper.removeOnLineListener(listener)
GlassMediaServiceHelper.removePhotoCallback(photoCallback)
} }
override fun onDestroy() { override fun onDestroy() {
isCaptureInFlight = false
hasNavigatedNextPage = false
super.onDestroy() super.onDestroy()
window.clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) window.clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
} }
private fun startCapture() {
if (isCaptureInFlight || hasNavigatedNextPage || taskNoFromIntent.isBlank()) {
return
}
binding.hint.text = "拍照中,请稍后..."
isPhoto = true
isCaptureInFlight = true
takePhoto()
}
private fun takePhoto() {
val fileName = "composite_layup_${System.currentTimeMillis()}.png"
val publicPicturesDir =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
val file = File(publicPicturesDir, fileName)
GlassMediaServiceHelper.takePhoto(PhotoResolution.RESOLUTION_720P, file.absolutePath)
}
private val adapter: BasePagedAdapter<ItemItem> =
object : CommonPagedAdapter<ItemItem>(R.layout.item_photo) {
override fun convert(holder: ViewHolder, item: ItemItem, position: Int) {
holder.setText(R.id.text, item.text)
.setClickListener(R.id.photo) {
if (item.text == "开始任务") {
startCapture()
}
}
}
}
override fun adapter(): BasePagedAdapter<ItemItem> = adapter
companion object { companion object {
const val EXTRA_TASK_NO = "extra_task_no" const val EXTRA_TASK_NO = "extra_task_no"
const val EXTRA_STEP_SEQ = "extra_step_seq"
} }
} }

查看文件

@ -56,8 +56,8 @@ class WelcomeActivity : BaseActivity<ActivityWelcomeBinding>() {
binding.tv.setOnClickListener { binding.tv.setOnClickListener {
runWithNetwork { runWithNetwork {
// triggerRecognize() // triggerRecognize()
// startActivity(Intent(this, TaskListActivity::class.java)) startActivity(Intent(this, TaskListActivity::class.java))
startActivity(Intent(this, ChatActivity::class.java)) // startActivity(Intent(this, ChatActivity::class.java))
} }
} }
} }

查看文件

@ -0,0 +1,68 @@
package com.nova.brain.glass.viewmodel
import androidx.lifecycle.MutableLiveData
import com.nova.brain.glass.MyApplication
import com.nova.brain.glass.model.ItemItem
import com.nova.brain.glass.model.data.CompositeLayupRecognizeResult
import com.nova.brain.glass.repository.Service4
import com.xuqm.base.di.manager.HttpManager
import com.xuqm.base.viewmodel.BaseListViewModel
import com.xuqm.base.viewmodel.callback.Response
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import java.io.File
enum class CompositeLayupResultState { IDLE, LOADING, SUCCESS, FAILED }
class CompositeLayupResultVM : BaseListViewModel<ItemItem>() {
val resultState = MutableLiveData(CompositeLayupResultState.IDLE)
val recognizeResult = MutableLiveData<CompositeLayupRecognizeResult?>()
val errorMessage = MutableLiveData<String>()
private val disposables = CompositeDisposable()
override fun loadData(page: Int, onResponse: Response<ItemItem>) {
onResponse.onResponse(arrayListOf())
}
fun recognize(taskNo: String, stepSeq: Int, photoPath: String) {
val file = File(photoPath)
if (!file.exists()) {
resultState.value = CompositeLayupResultState.FAILED
errorMessage.value = "图片不存在"
return
}
resultState.value = CompositeLayupResultState.LOADING
val taskNoBody = taskNo.toRequestBody("text/plain".toMediaTypeOrNull())
val stepSeqBody = stepSeq.toString().toRequestBody("text/plain".toMediaTypeOrNull())
val requestFile = file.asRequestBody("application/octet-stream".toMediaTypeOrNull())
val filePart = MultipartBody.Part.createFormData("file", file.name, requestFile)
val disposable = HttpManager.getApi(MyApplication.appComponent4, Service4::class.java)
.ocrRecognize(taskNoBody, stepSeqBody, filePart)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ response ->
if (response.success && response.data != null) {
recognizeResult.value = response.data
resultState.value = CompositeLayupResultState.SUCCESS
} else {
resultState.value = CompositeLayupResultState.FAILED
errorMessage.value = response.message.ifBlank { "OCR识别失败" }
}
}, { e ->
resultState.value = CompositeLayupResultState.FAILED
errorMessage.value = e.message ?: "OCR识别失败"
})
disposables.add(disposable)
}
override fun onCleared() {
super.onCleared()
disposables.clear()
}
}

查看文件

@ -2,12 +2,14 @@ package com.nova.brain.glass.viewmodel
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import com.nova.brain.glass.MyApplication import com.nova.brain.glass.MyApplication
import com.nova.brain.glass.model.ItemItem
import com.nova.brain.glass.model.data.CompositeLayupRecognizeResult import com.nova.brain.glass.model.data.CompositeLayupRecognizeResult
import com.nova.brain.glass.model.data.CompositeLayupDetailItem import com.nova.brain.glass.model.data.CompositeLayupDetailItem
import com.nova.brain.glass.model.data.CompositeLayupTaskDetail import com.nova.brain.glass.model.data.CompositeLayupTaskDetail
import com.nova.brain.glass.repository.Service4 import com.nova.brain.glass.repository.Service4
import com.xuqm.base.di.manager.HttpManager import com.xuqm.base.di.manager.HttpManager
import androidx.lifecycle.ViewModel import com.xuqm.base.viewmodel.BaseListViewModel
import com.xuqm.base.viewmodel.callback.Response
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers import io.reactivex.schedulers.Schedulers
@ -19,7 +21,7 @@ import java.io.File
enum class CompositeLayupRecognizeState { IDLE, LOADING, SUCCESS, FAILED } enum class CompositeLayupRecognizeState { IDLE, LOADING, SUCCESS, FAILED }
class CompositeLayupTaskVM : ViewModel() { class CompositeLayupTaskVM : BaseListViewModel<ItemItem>() {
val taskDetail = MutableLiveData<CompositeLayupTaskDetail?>() val taskDetail = MutableLiveData<CompositeLayupTaskDetail?>()
val taskDetailError = MutableLiveData<String>() val taskDetailError = MutableLiveData<String>()
@ -36,15 +38,19 @@ class CompositeLayupTaskVM : ViewModel() {
var lastRecognizeFinished: Boolean = false var lastRecognizeFinished: Boolean = false
private set private set
fun loadTaskDetail(taskNo: String) { override fun loadData(page: Int, onResponse: Response<ItemItem>) {
onResponse.onResponse(arrayListOf(ItemItem("开始任务")))
}
fun loadTaskDetail(taskNo: String, stepOverride: Int? = null) {
this.taskNo = taskNo this.taskNo = taskNo
val disposable = HttpManager.getApi(MyApplication.appComponent4, Service4::class.java) val disposable = HttpManager.getApi(MyApplication.appComponent4, Service4::class.java)
.queryTask(taskNo) .queryTask(taskNo)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe({ response -> .subscribe({ response ->
if (response.success && response.data != null) { if (response.code == 200 && response.data != null) {
bindTaskDetail(response.data) bindTaskDetail(response.data, stepOverride)
} else { } else {
taskDetailError.value = response.message.ifBlank { "获取任务详情失败" } taskDetailError.value = response.message.ifBlank { "获取任务详情失败" }
} }
@ -100,9 +106,6 @@ class CompositeLayupTaskVM : ViewModel() {
fun currentDetail(): CompositeLayupDetailItem? = fun currentDetail(): CompositeLayupDetailItem? =
taskDetail.value?.detailList taskDetail.value?.detailList
?.sortedBy { it.stepSeq }
?.firstOrNull { it.stepSeq == currentStepSeq }
?: taskDetail.value?.detailList
?.sortedBy { it.stepSeq } ?.sortedBy { it.stepSeq }
?.getOrNull((currentStepSeq - 1).coerceAtLeast(0)) ?.getOrNull((currentStepSeq - 1).coerceAtLeast(0))
@ -121,16 +124,13 @@ class CompositeLayupTaskVM : ViewModel() {
return true return true
} }
private fun bindTaskDetail(detail: CompositeLayupTaskDetail) { private fun bindTaskDetail(detail: CompositeLayupTaskDetail, stepOverride: Int? = null) {
taskDetail.value = detail taskDetail.value = detail
this.taskNo = detail.taskNo.ifBlank { taskNo } this.taskNo = detail.taskNo.ifBlank { taskNo }
totalSteps = detail.taskSteps.coerceAtLeast(detail.detailList?.size ?: 1).coerceAtLeast(1) totalSteps = detail.taskSteps.coerceAtLeast(detail.detailList?.size ?: 1).coerceAtLeast(1)
currentStepSeq = when { currentStepSeq = when {
stepOverride != null && stepOverride > 0 -> stepOverride
detail.taskCurrentStep > 0 -> detail.taskCurrentStep detail.taskCurrentStep > 0 -> detail.taskCurrentStep
!detail.detailList.isNullOrEmpty() -> {
detail.detailList.firstOrNull { it.detailStatus != 9 }?.stepSeq
?: detail.detailList.last().stepSeq.coerceAtLeast(1)
}
else -> 1 else -> 1
}.coerceIn(1, totalSteps) }.coerceIn(1, totalSteps)
lastRecognizeFinished = currentStepSeq >= totalSteps lastRecognizeFinished = currentStepSeq >= totalSteps

查看文件

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<layout>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/app_color_black">
<ImageView
android:id="@+id/icon"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_marginTop="44dp"
android:src="@mipmap/ocr_true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:text="铺贴层与零件信息正确"
android:textColor="#ff40FF5E"
android:textSize="22sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/icon" />
<TextView
android:id="@+id/subtitle1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="识别到这是1/12张"
android:textColor="#ff40FF5E"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title" />
<TextView
android:id="@+id/subtitle2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="请真空铺贴、纹理方向+90"
android:textColor="#ff40FF5E"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/subtitle1" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/baseRecyclerView"
android:layout_width="0dp"
android:layout_height="88dp"
android:layout_marginTop="24dp"
android:clipToPadding="false"
android:overScrollMode="never"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/subtitle2" />
<TextView
android:id="@+id/hint"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:gravity="center"
android:text="单击或语音输入“开始铺贴”,进入下一步"
android:textColor="#ff40FF5E"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/baseRecyclerView" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

查看文件

@ -55,7 +55,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="15dp" android:layout_marginStart="15dp"
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
android:text="零件号:20293989-001" android:text="零件号:"
android:textColor="#ff40FF5E" android:textColor="#ff40FF5E"
android:textSize="14sp" /> android:textSize="14sp" />
@ -65,7 +65,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="15dp" android:layout_marginStart="15dp"
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
android:text="任务编号:PT20260422001" android:text="任务编号:"
android:textColor="#ff40FF5E" android:textColor="#ff40FF5E"
android:textSize="14sp" /> android:textSize="14sp" />
@ -75,7 +75,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="15dp" android:layout_marginStart="15dp"
android:layout_marginVertical="4dp" android:layout_marginVertical="4dp"
android:text="任务进度:1/12" android:text="任务进度:"
android:textColor="#ff40FF5E" android:textColor="#ff40FF5E"
android:textSize="14sp" /> android:textSize="14sp" />
</LinearLayout> </LinearLayout>
@ -84,8 +84,8 @@
android:id="@+id/baseRecyclerView" android:id="@+id/baseRecyclerView"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="88dp" android:layout_height="88dp"
android:layout_marginTop="24dp"
android:clipToPadding="false" android:clipToPadding="false"
android:layout_marginTop="12dp"
android:overScrollMode="never" android:overScrollMode="never"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@ -93,238 +93,17 @@
<TextView <TextView
android:id="@+id/hint" android:id="@+id/hint"
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="12dp" android:layout_marginStart="15dp"
android:layout_marginTop="10dp"
android:layout_marginVertical="4dp"
android:gravity="center" android:gravity="center"
android:text="单击或语音输入&#34;开始&#34;,进入下一步" android:text="单击或语音输入&#34;开始&#34;,进入下一步"
android:textColor="#ff40FF5E" android:textColor="#ff40FF5E"
android:textSize="14sp" android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/baseRecyclerView" /> app:layout_constraintTop_toBottomOf="@+id/baseRecyclerView" />
<FrameLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="24dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="24dp"
android:layout_marginBottom="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/hint">
<LinearLayout
android:id="@+id/groupStart"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<FrameLayout
android:layout_width="128dp"
android:layout_height="128dp"
android:background="@drawable/bg_composite_circle">
<ImageView
android:id="@+id/startIcon"
android:layout_width="52dp"
android:layout_height="52dp"
android:layout_gravity="center"
android:src="@mipmap/ocr_photo" />
</FrameLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/groupCapture"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<FrameLayout
android:layout_width="320dp"
android:layout_height="220dp">
<View
android:layout_width="60dp"
android:layout_height="4dp"
android:background="#ff40FF5E" />
<View
android:layout_width="4dp"
android:layout_height="60dp"
android:background="#ff40FF5E" />
<View
android:layout_width="60dp"
android:layout_height="4dp"
android:layout_gravity="top|end"
android:background="#ff40FF5E" />
<View
android:layout_width="4dp"
android:layout_height="60dp"
android:layout_gravity="top|end"
android:background="#ff40FF5E" />
<View
android:layout_width="60dp"
android:layout_height="4dp"
android:layout_gravity="bottom|start"
android:background="#ff40FF5E" />
<View
android:layout_width="4dp"
android:layout_height="60dp"
android:layout_gravity="bottom|start"
android:background="#ff40FF5E" />
<View
android:layout_width="60dp"
android:layout_height="4dp"
android:layout_gravity="bottom|end"
android:background="#ff40FF5E" />
<View
android:layout_width="4dp"
android:layout_height="60dp"
android:layout_gravity="bottom|end"
android:background="#ff40FF5E" />
<TextView
android:id="@+id/captureMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="请对准复材铺贴物料上的字符内容"
android:textColor="#ff40FF5E"
android:textSize="16sp" />
</FrameLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/groupResult"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:id="@+id/resultIcon"
android:layout_width="120dp"
android:layout_height="120dp"
android:src="@mipmap/ocr_true" />
<TextView
android:id="@+id/resultTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:gravity="center"
android:text="铺贴层与料号信息正确"
android:textColor="#ff40FF5E"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:id="@+id/resultSubtitle1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="识别到这是1/12张"
android:textColor="#ff40FF5E"
android:textSize="18sp" />
<TextView
android:id="@+id/resultSubtitle2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="请真空铺贴、纹理方向+90"
android:textColor="#ff40FF5E"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/groupWork"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<TextView
android:id="@+id/workText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:lineSpacingExtra="6dp"
android:text="请进行铺贴工作"
android:textColor="#ff40FF5E"
android:textSize="22sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/groupConfirm"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<TextView
android:id="@+id/confirmTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="请确认是否已完成第3/12张铺贴"
android:textColor="#ff40FF5E"
android:textSize="22sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/groupComplete"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:layout_width="120dp"
android:layout_height="120dp"
android:src="@mipmap/ocr_true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:gravity="center"
android:text="恭喜完成当前铺贴任务!"
android:textColor="#ff40FF5E"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:id="@+id/completeSubtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:gravity="center"
android:text="3S后自动返回铺贴任务界面"
android:textColor="#ff40FF5E"
android:textSize="18sp" />
</LinearLayout>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout> </layout>

查看文件

@ -103,13 +103,5 @@
android:text="单击或语音输入“开始”,进入下一步" android:text="单击或语音输入“开始”,进入下一步"
android:textColor="#ff40FF5E" android:textColor="#ff40FF5E"
android:textSize="14sp"/> android:textSize="14sp"/>
<ImageView
android:layout_width="120dp"
android:id="@+id/iv"
android:layout_height="150dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/hint"/>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout> </layout>