package com.shlb.comb.activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.text.Html; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.ScrollView; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton; import com.shlb.comb.R; import com.shlb.comb.base.BaseActivity; import com.shlb.comb.event.UpdateEvent; import com.shlb.comb.manager.BleGlobalManager; import com.shlb.comb.util.CMD; import com.shlb.comb.util.CRCutil; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; public class ParameterSettingActivity extends BaseActivity { // 阈值设定相关控件 private Spinner sp_threshold_mode; private EditText et_threshold_value; private Button btn_threshold_write; // 灵敏度设定相关控件 private Spinner sp_sensitivity_mode; private EditText et_sensitivity_value; private Button btn_sensitivity_write; // 自检和复位按钮 private Button btn_start_check; private Button btn_end_check; private Button btn_reset_mainboard; private Button btn_reset_sensor; // 日志和状态显示 private TextView tv_log; private TextView tv_right_text; private androidx.cardview.widget.CardView cvLog; // 自检监测网格和日志控件 private RecyclerView rvGrid; private QMUIRoundButton btnReadData; private QMUIRoundButton btnClearLog; private ScrollView svLog; // 数据相关 private GridAdapter mAdapter; private List boxStatusList = new ArrayList<>(); private StringBuilder logBuilder = new StringBuilder(); private boolean isSelfCheckMode = false; // 标记当前是否处于自检模式 private String pendingSettingCmd = ""; // 记录待处理的设定指令 private Button currentOperatingButton; // 当前正在操作的按钮 private String pendingToastMessage = null; // 待显示的Toast消息 private SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); @Override protected void contentView() { setContentView(R.layout.activity_parameter_setting); } @Override protected void initView() { super.initHead(); if (tv_center != null) { tv_center.setText("参数设定"); } if (iv_left != null) { iv_left.setImageResource(R.mipmap.icon_back); } sp_threshold_mode = findViewById(R.id.sp_threshold_mode); et_threshold_value = findViewById(R.id.et_threshold_value); btn_threshold_write = findViewById(R.id.btn_threshold_write); sp_sensitivity_mode = findViewById(R.id.sp_sensitivity_mode); et_sensitivity_value = findViewById(R.id.et_sensitivity_value); btn_sensitivity_write = findViewById(R.id.btn_sensitivity_write); btn_start_check = findViewById(R.id.btn_start_check); btn_end_check = findViewById(R.id.btn_end_check); btn_reset_mainboard = findViewById(R.id.btn_reset_mainboard); btn_reset_sensor = findViewById(R.id.btn_reset_sensor); tv_log = findViewById(R.id.tv_log); cvLog = findViewById(R.id.cv_log); tv_right_text = findViewById(R.id.tv_right_text); // 初始化自检监测相关控件 rvGrid = findViewById(R.id.rv_grid); btnClearLog = findViewById(R.id.btn_clear_log); svLog = findViewById(R.id.sv_log); // 设置日志滚动视图的触摸监听,防止滑动冲突 if (svLog != null) { svLog.setOnTouchListener((v, event) -> { v.getParent().requestDisallowInterceptTouchEvent(true); if ((event.getAction() & android.view.MotionEvent.ACTION_MASK) == android.view.MotionEvent.ACTION_UP) { v.getParent().requestDisallowInterceptTouchEvent(false); } return false; }); } // 初始化日志内容 if (logBuilder.length() > 0) { tv_log.setText(Html.fromHtml(logBuilder.toString())); } else { logBuilder.append("日志记录:
"); tv_log.setText(Html.fromHtml(logBuilder.toString())); } } @Override protected void initData() { updateBluetoothStatus(); // 初始化30个格子的状态列表 boxStatusList.clear(); for (int i = 1; i <= 30; i++) { boxStatusList.add(new BoxStatus(i)); } // 设置网格布局:3行10列 rvGrid.setLayoutManager(new GridLayoutManager(this, 10)); mAdapter = new GridAdapter(); rvGrid.setAdapter(mAdapter); // 如果蓝牙已连接,进入设定模式 if (BleGlobalManager.getInstance().isConnected()) { sendCmdWithCrc(CMD.ENTER_SETTING); } } @Override protected void onResume() { super.onResume(); // 根据系统设置控制日志显示 boolean isCmdLogEnabled = com.blankj.utilcode.util.SPUtils.getInstance().getBoolean("cmd_log_enabled", false); if (cvLog != null) { cvLog.setVisibility(isCmdLogEnabled ? View.VISIBLE : View.GONE); } } @Override protected void onDestroy() { // 页面销毁时退出设定模式 if (BleGlobalManager.getInstance().isConnected()) { sendCmdWithCrc(CMD.EXIT_SETTING); } super.onDestroy(); } @Override protected void initEvent() { View.OnClickListener listener = new View.OnClickListener() { @Override public void onClick(View v) { int id = v.getId(); String action = ""; if (id == R.id.btn_threshold_write) { handleThresholdWrite(); } else if (id == R.id.btn_sensitivity_write) { handleSensitivityWrite(); } else if (id == R.id.btn_start_check) { if (BleGlobalManager.getInstance().isConnected()) { currentOperatingButton = btn_start_check; updateButtonState(currentOperatingButton, false); action = "开始自检"; setAllGridGray(); sendCmdWithCrc(CMD.WRITE_START_CHECK); isSelfCheckMode = true; } else { Toast.makeText(ParameterSettingActivity.this, "请先连接蓝牙", Toast.LENGTH_SHORT).show(); } } else if (id == R.id.btn_end_check) { if (BleGlobalManager.getInstance().isConnected()) { currentOperatingButton = btn_end_check; updateButtonState(currentOperatingButton, false); action = "结束自检"; setAllGridGray(); sendCmdWithCrc(CMD.WRITE_END_CHECK); isSelfCheckMode = false; } else { Toast.makeText(ParameterSettingActivity.this, "请先连接蓝牙", Toast.LENGTH_SHORT).show(); } } else if (id == R.id.btn_reset_mainboard) { currentOperatingButton = btn_reset_mainboard; showResetConfirmDialog("确定要执行主板复位吗?", CMD.WRITE_BOARD_RESET); } else if (id == R.id.btn_reset_sensor) { currentOperatingButton = btn_reset_sensor; showResetConfirmDialog("确定要执行传感器复位吗?", CMD.WRITE_SENSOR_RESET); } if (!action.isEmpty()) { // Toast.makeText(ParameterSettingActivity.this, action, Toast.LENGTH_SHORT).show(); // appendLog(action); } } }; btn_threshold_write.setOnClickListener(listener); btn_sensitivity_write.setOnClickListener(listener); btn_start_check.setOnClickListener(listener); btn_end_check.setOnClickListener(listener); btn_reset_mainboard.setOnClickListener(listener); btn_reset_sensor.setOnClickListener(listener); // 阈值模式选择监听,控制输入框是否可用 sp_threshold_mode.setOnItemSelectedListener(new android.widget.AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(android.widget.AdapterView parent, View view, int position, long id) { if (position == 0) { // 一键设定,隐藏输入框 (使用INVISIBLE保留占位,防止按钮移位) et_threshold_value.setVisibility(View.INVISIBLE); et_threshold_value.setText(""); } else { // 单层设定,显示输入框 et_threshold_value.setVisibility(View.VISIBLE); int maxLayer = com.blankj.utilcode.util.SPUtils.getInstance().getInt("layer_count", 30); et_threshold_value.setHint("1-" + maxLayer); } } @Override public void onNothingSelected(android.widget.AdapterView parent) { } }); // 灵敏度模式选择监听,控制输入框是否可用 sp_sensitivity_mode.setOnItemSelectedListener(new android.widget.AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(android.widget.AdapterView parent, View view, int position, long id) { // 0: 批量增加, 1: 批量减少, 2: 单层增加, 3: 单层减少 if (position == 0 || position == 1) { // 批量操作,隐藏输入框 et_sensitivity_value.setVisibility(View.INVISIBLE); et_sensitivity_value.setText(""); } else { // 单层操作,显示输入框 et_sensitivity_value.setVisibility(View.VISIBLE); int maxLayer = com.blankj.utilcode.util.SPUtils.getInstance().getInt("layer_count", 30); et_sensitivity_value.setHint("1-" + maxLayer); } } @Override public void onNothingSelected(android.widget.AdapterView parent) { } }); btnClearLog.setOnClickListener(v -> { logBuilder.setLength(0); logBuilder.append("日志记录:
"); tv_log.setText(Html.fromHtml(logBuilder.toString())); }); } private String getCmdDescription(String hex, Boolean isSent) { if (hex == null) return ""; // 进入/退出设定模式指令特殊处理 if (hex.startsWith(CMD.ENTER_SETTING.substring(0, 8))) { if (hex.startsWith(CMD.ENTER_SETTING)) return "-进入设定"; if (hex.startsWith(CMD.EXIT_SETTING)) return "-退出设定"; } // 发送指令匹配 if (hex.startsWith(CMD.WRITE_THRESHOLD_SETTING)) return "-阈值设定"; if (hex.startsWith(CMD.WRITE_SENSITIVITY_SETTING)) return "-灵敏度设定"; if (hex.startsWith(CMD.WRITE_BOARD_RESET)) return "-主板复位"; if (hex.startsWith(CMD.WRITE_SENSOR_RESET)) return "-传感器复位"; if (hex.startsWith(CMD.WRITE_START_CHECK)) return "-开始自检"; if (hex.startsWith(CMD.WRITE_END_CHECK)) return "-结束自检"; if (hex.startsWith(CMD.READ_DATA.substring(0, 8))) return "-读数据"; // 接收数据匹配 if (hex.startsWith(CMD.WRITE_THRESHOLD_SETTING.substring(0, 8))) return "-阈值返回"; if (hex.startsWith(CMD.WRITE_SENSITIVITY_SETTING.substring(0, 8))) return "-灵敏度返回"; if (hex.startsWith(CMD.WRITE_BOARD_RESET.substring(0, 8))) return "-主板复位返回"; if (hex.startsWith(CMD.WRITE_SENSOR_RESET.substring(0, 8))) return "-传感器复位返回"; if (hex.startsWith(CMD.WRITE_START_CHECK.substring(0, 8))) return "-自检返回"; if (hex.startsWith(CMD.WRITE_SUFFIX)) return "-写入返回"; return ""; } private void appendLog(String msg) { appendLog(msg, null); } private void appendLog(String msg, Boolean isSent) { String time = new SimpleDateFormat("HH:mm:ss.SSS", Locale.getDefault()).format(new Date()); String displayMsg = msg; String cmdDesc = ""; // 如果是十六进制指令,每两位加一个空格格式化显示 if (msg.matches("^[0-9A-Fa-f]+$")) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < msg.length(); i += 2) { if (i + 2 <= msg.length()) { sb.append(msg.substring(i, i + 2)).append(" "); } else { sb.append(msg.substring(i)); } } displayMsg = sb.toString().trim(); // 获取指令描述 cmdDesc = getCmdDescription(msg, isSent); } String logLine; if (isSent != null) { // 发送指令用蓝色,接收数据用绿色 String color = isSent ? "#1890ff" : "#05aa87"; String prefix = (isSent ? "发送" : "收到") + cmdDesc + ": "; logLine = time + " " + prefix + displayMsg + "
"; } else { // 普通日志 logLine = time + " " + displayMsg + "
"; } logBuilder.append(logLine); // 更新日志显示并自动滚动到底部 if (tv_log != null) { tv_log.setText(Html.fromHtml(logBuilder.toString())); if (svLog != null) { svLog.post(() -> svLog.fullScroll(View.FOCUS_DOWN)); } } } // 兼容旧代码的日志方法 private void addLog(String message) { appendLog(message); } @Subscribe(threadMode = ThreadMode.MAIN) public void onEvent(UpdateEvent event) { if (event.getType() == UpdateEvent.Type.CONN_STATU) { updateBluetoothStatus(); } else if (event.getType() == UpdateEvent.Type.DEVICE_INFO) { String hex = event.getMsg(); appendLog(hex, false); // false表示接收的数据,显示为绿色 parseAndRefresh(hex); } } private void parseAndRefresh(String hex) { if (hex == null) return; // 处理写入指令的返回(A55A06开头) if (hex.startsWith(CMD.WRITE_SUFFIX) && hex.length() >= 12) { // 提取状态字节,01表示成功 String statusHex = hex.substring(10, 12); boolean isSuccess = "01".equals(statusHex); // 处理进入设定模式的返回 if (hex.startsWith(CMD.ENTER_SETTING.substring(0, 8))) { if (isSuccess) { appendLog("进入设定模式成功"); } else { appendLog("进入设定模式失败"); } return; } // 处理退出设定模式的返回 if (hex.startsWith(CMD.EXIT_SETTING.substring(0, 8))) { appendLog("退出设定模式成功"); return; } // 处理阈值设定的返回 if (hex.startsWith(CMD.WRITE_THRESHOLD_SETTING.substring(0, 8))) { if (isSuccess) { appendLog("阈值写入成功"); pendingToastMessage = "阈值写入成功"; // 阈值写入成功后,等待500毫秒再读取数据 appendLog("500毫秒后读取阈值设定结果..."); new android.os.Handler().postDelayed(() -> { sendCmdWithCrc(CMD.READ_DATA); }, 500); } else { restoreCurrentButton(); appendLog("阈值写入失败"); Toast.makeText(this, "阈值写入失败", Toast.LENGTH_SHORT).show(); } } else if (hex.startsWith(CMD.WRITE_SENSITIVITY_SETTING.substring(0, 8))) { // 处理灵敏度设定的返回 if (isSuccess) { appendLog("灵敏度写入成功"); pendingToastMessage = "灵敏度写入成功"; // 灵敏度写入成功后,等待500毫秒再读取数据 appendLog("500毫秒后读取灵敏度设定结果..."); new android.os.Handler().postDelayed(() -> { sendCmdWithCrc(CMD.READ_DATA); }, 500); } else { restoreCurrentButton(); appendLog("灵敏度写入失败"); Toast.makeText(this, "灵敏度写入失败", Toast.LENGTH_SHORT).show(); } } else if (hex.startsWith(CMD.WRITE_BOARD_RESET.substring(0, 8))) { // 处理主板/传感器复位的返回 // 判断是主板复位还是传感器复位 boolean isBoardReset = pendingSettingCmd.equals(CMD.WRITE_BOARD_RESET); String name = isBoardReset ? "主板复位" : "传感器复位"; if (isSuccess) { appendLog(name + "成功"); // 如果是主板复位成功,提示即将返回并跳转到实时监控页面 if (isBoardReset) { Toast.makeText(this, "复位成功即将返回", Toast.LENGTH_SHORT).show(); appendLog("复位成功,2秒后返回实时监控页面..."); // 2秒后返回到实时监控页面 new android.os.Handler().postDelayed(() -> { finish(); // 关闭当前页面,返回到实时监控页面 }, 2000); } else { // 传感器复位成功,提示并在500毫秒后读取数据 Toast.makeText(this, name + "成功", Toast.LENGTH_SHORT).show(); // 500毫秒后读取数据,通过现有的parseSelfCheckData解析 new android.os.Handler().postDelayed(() -> { sendCmdWithCrc(CMD.READ_DATA); }, 500); } } else { restoreCurrentButton(); appendLog(name + "失败"); Toast.makeText(this, name + "失败", Toast.LENGTH_SHORT).show(); } } } // 处理自检指令的返回结果 // 开始自检和结束自检的指令前缀相同,都是 CMD.WRITE_START_CHECK 的前8位 if (hex.startsWith(CMD.WRITE_START_CHECK.substring(0, 8)) && hex.length() >= 12) { // 提取状态字节(第11-12位),01表示成功,其他表示失败 String statusHex = hex.substring(10, 12); boolean isSuccess = "01".equals(statusHex); // 根据当前模式判断操作名称 String opName = isSelfCheckMode ? "开始自检" : "结束自检"; if (isSuccess) { appendLog(opName + "成功"); pendingToastMessage = opName + "成功"; // 根据不同的自检阶段,延迟不同时间后读取数据 if (isSelfCheckMode) { // 开始自检成功后,等待 层数 * 1000 毫秒再读取数据 int layerCount = com.blankj.utilcode.util.SPUtils.getInstance().getInt("layer_count", 3); long delay = layerCount * 1000L; Toast.makeText(this, "开始自检,请等待" + layerCount + "秒", Toast.LENGTH_SHORT).show(); // 这个时间是为了让传感器完成自检动作 appendLog(delay + "毫秒后读取自检结果..."); new android.os.Handler().postDelayed(() -> { sendCmdWithCrc(CMD.READ_DATA); }, delay); } else { // 结束自检成功后,等待500毫秒再读取数据 // 这个时间是为了让设备状态稳定后再读取最终结果 appendLog("500毫秒后读取自检结果..."); new android.os.Handler().postDelayed(() -> { sendCmdWithCrc(CMD.READ_DATA); }, 500); } } else { appendLog(opName + "失败"); Toast.makeText(this, opName + "失败", Toast.LENGTH_SHORT).show(); } } // 处理读取数据指令的返回结果,用于显示自检结果 // 数据格式:A55A0301... 至少需要26位十六进制字符 if (hex.startsWith(CMD.READ_DATA.substring(0, 8)) && hex.length() >= 26) { restoreCurrentButton(); parseSelfCheckData(hex); if (pendingToastMessage != null) { Toast.makeText(this, pendingToastMessage, Toast.LENGTH_SHORT).show(); pendingToastMessage = null; } } } /** * 解析自检数据并更新格子状态 * @param hex 接收到的十六进制数据 */ private void parseSelfCheckData(String hex) { try { // 提取第11-18位(8个字符)作为第一部分数据 String part1Hex = hex.substring(10, 18); long part1Bits = Long.parseLong(part1Hex, 16); // 提取第19-26位(8个字符)作为第二部分数据 String part2Hex = hex.substring(18, 26); long part2Bits = Long.parseLong(part2Hex, 16); appendLog("自检数据解析: " + part1Hex + ", " + part2Hex); boolean hasChange = false; // 遍历所有格子,根据位数据判断自检结果 for (BoxStatus box : boxStatusList) { int bitIndex = box.id - 1; // 格子ID从1开始,位索引从0开始 if (bitIndex >= 0 && bitIndex < 32) { // 提取对应位的值 boolean bit1 = ((part1Bits >> bitIndex) & 1) == 1; boolean bit2 = ((part2Bits >> bitIndex) & 1) == 1; // 两个位都为1表示自检成功,否则失败 if (bit1 && bit2) { box.checkResult = 1; // 成功,显示绿色 } else { box.checkResult = 0; // 失败,显示红色 } hasChange = true; } } // 如果有数据变化,刷新界面 if (hasChange && mAdapter != null) { mAdapter.notifyDataSetChanged(); appendLog("自检结果已更新"); } } catch (Exception e) { e.printStackTrace(); appendLog("自检数据解析异常: " + e.getMessage()); } } /** * 发送带CRC校验的指令 * @param cmd 要发送的指令(不含CRC) */ private void sendCmdWithCrc(String cmd) { if (!BleGlobalManager.getInstance().isConnected()) { Toast.makeText(this, "请先连接蓝牙", Toast.LENGTH_SHORT).show(); appendLog("错误: 蓝牙未连接"); return; } byte[] cmdBytes = BleGlobalManager.hexStringToBytes(cmd); if (cmdBytes != null) { // 计算CRC校验码 String crc = CRCutil.getCRC(cmdBytes); // CRC补齐到4位 while (crc.length() < 4) { crc = "0" + crc; } String fullCmd = cmd + crc.toUpperCase(); appendLog(fullCmd, true); // true表示发送的指令,显示为蓝色 BleGlobalManager.getInstance().sendCmd(fullCmd); } else { appendLog("错误: 指令转换失败"); } } /** * 处理阈值设定写入 */ private void handleThresholdWrite() { int position = sp_threshold_mode.getSelectedItemPosition(); String inputValue = et_threshold_value.getText().toString().trim(); String modeHex = ""; String valueHex = ""; if (position == 0) { // 一键设定 modeHex = "00"; valueHex = "00"; } else if (position == 1) { // 单层设定 modeHex = "01"; int maxLayer = com.blankj.utilcode.util.SPUtils.getInstance().getInt("layer_count", 30); if (inputValue.isEmpty()) { Toast.makeText(this, "请输入阈值(1-" + maxLayer + ")", Toast.LENGTH_SHORT).show(); return; } try { int val = Integer.parseInt(inputValue); if (val < 1 || val > maxLayer) { Toast.makeText(this, "阈值范围1-" + maxLayer, Toast.LENGTH_SHORT).show(); return; } // 单层设定时,输入参数需要减1 valueHex = String.format("%02X", val - 1); } catch (NumberFormatException e) { Toast.makeText(this, "输入格式错误", Toast.LENGTH_SHORT).show(); return; } } else { return; } // 构造指令:CMD.WRITE_THRESHOLD_SETTING + 模式 + 值 pendingSettingCmd = CMD.WRITE_THRESHOLD_SETTING + modeHex + valueHex; if (BleGlobalManager.getInstance().isConnected()) { currentOperatingButton = btn_threshold_write; updateButtonState(currentOperatingButton, false); setAllGridGray(); sendCmdWithCrc(pendingSettingCmd); } else { Toast.makeText(this, "请先连接蓝牙", Toast.LENGTH_SHORT).show(); } } /** * 将所有格子设置为灰色(等待状态) */ private void setAllGridGray() { for (BoxStatus box : boxStatusList) { box.checkResult = 2; // 2表示等待状态,显示灰色 } if (mAdapter != null) { mAdapter.notifyDataSetChanged(); } } /** * 处理灵敏度设定写入 */ private void handleSensitivityWrite() { int position = sp_sensitivity_mode.getSelectedItemPosition(); String inputValue = et_sensitivity_value.getText().toString().trim(); String modeHex = ""; String valueHex = ""; // 模式:0=批量增加(00), 1=批量减少(01), 2=单层增加(02), 3=单层减少(03) if (position == 0) { modeHex = "00"; valueHex = "00"; } else if (position == 1) { modeHex = "01"; valueHex = "00"; } else if (position == 2) { modeHex = "02"; } else if (position == 3) { modeHex = "03"; } else { return; } // 单层操作需要输入具体数值 if (position == 2 || position == 3) { int maxLayer = com.blankj.utilcode.util.SPUtils.getInstance().getInt("layer_count", 30); if (inputValue.isEmpty()) { Toast.makeText(this, "请输入数值(1-" + maxLayer + ")", Toast.LENGTH_SHORT).show(); return; } try { int val = Integer.parseInt(inputValue); if (val < 1 || val > maxLayer) { Toast.makeText(this, "数值范围1-" + maxLayer, Toast.LENGTH_SHORT).show(); return; } // 单层设定时,输入参数需要减1 valueHex = String.format("%02X", val - 1); } catch (NumberFormatException e) { Toast.makeText(this, "输入格式错误", Toast.LENGTH_SHORT).show(); return; } } // 构造指令:CMD.WRITE_SENSITIVITY_SETTING + 模式 + 值 pendingSettingCmd = CMD.WRITE_SENSITIVITY_SETTING + modeHex + valueHex; if (BleGlobalManager.getInstance().isConnected()) { currentOperatingButton = btn_sensitivity_write; updateButtonState(currentOperatingButton, false); setAllGridGray(); sendCmdWithCrc(pendingSettingCmd); } else { Toast.makeText(this, "请先连接蓝牙", Toast.LENGTH_SHORT).show(); } } private void updateBluetoothStatus() { if (tv_right_text == null) return; if (BleGlobalManager.getInstance().isConnected()) { String name = "未知设备"; if (BleGlobalManager.getInstance().getBluetoothLeDevice() != null) { String deviceName = BleGlobalManager.getInstance().getBluetoothLeDevice().getName(); if (deviceName != null && !deviceName.isEmpty()) { name = deviceName; } } tv_right_text.setText(name); } else { tv_right_text.setText("未连接"); } } private void showResetConfirmDialog(String message, final String cmd) { new AlertDialog.Builder(this) .setTitle("提示") .setMessage(message) .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (BleGlobalManager.getInstance().isConnected()) { updateButtonState(currentOperatingButton, false); pendingSettingCmd = cmd; sendCmdWithCrc(cmd); } else { Toast.makeText(ParameterSettingActivity.this, "请先连接蓝牙", Toast.LENGTH_SHORT).show(); } } }) .setNegativeButton("取消", null) .show(); } /** * 格子状态数据类 */ private static class BoxStatus { int id; // 格子ID(1-30) int checkResult = -1; // 自检结果:-1=未知(白色),0=失败(红色),1=成功(绿色),2=等待(灰色) public BoxStatus(int id) { this.id = id; this.checkResult = -1; } } private class GridAdapter extends RecyclerView.Adapter { @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_grid_box, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { // 计算格子ID:3行10列,从左到右排列 // 第1行(位置0-9):1-10 // 第2行(位置10-19):11-20 // 第3行(位置20-29):21-30 int row = position / 10; int col = position % 10; int boxId = row * 10 + col + 1; holder.tvBoxNumber.setText(String.valueOf(boxId)); // 查找对应格子的状态 BoxStatus status = null; for (BoxStatus s : boxStatusList) { if (s.id == boxId) { status = s; break; } } // 根据自检结果设置背景颜色 if (status != null) { if (status.checkResult == 1) { // 自检成功,显示绿色 holder.viewBox.setBackgroundResource(R.drawable.bg_box_full); holder.viewBox.getBackground().clearColorFilter(); } else if (status.checkResult == 0) { // 自检失败,显示红色 holder.viewBox.setBackgroundResource(R.drawable.bg_box_error); holder.viewBox.getBackground().clearColorFilter(); } else if (status.checkResult == 2) { // 等待状态,显示灰色 holder.viewBox.setBackgroundResource(R.drawable.bg_box_empty); holder.viewBox.getBackground().setColorFilter(android.graphics.Color.GRAY, android.graphics.PorterDuff.Mode.MULTIPLY); } else { // 未知状态,显示白色 holder.viewBox.setBackgroundResource(R.drawable.bg_box_empty); holder.viewBox.getBackground().clearColorFilter(); } } } @Override public int getItemCount() { return 30; } class ViewHolder extends RecyclerView.ViewHolder { TextView tvBoxNumber; View viewBox; public ViewHolder(@NonNull View itemView) { super(itemView); tvBoxNumber = itemView.findViewById(R.id.tv_box_number); viewBox = itemView.findViewById(R.id.view_box); } } } private void restoreCurrentButton() { if (currentOperatingButton != null) { updateButtonState(currentOperatingButton, true); currentOperatingButton = null; } } private void updateButtonState(Button btn, boolean enable) { if (btn == null) return; btn.setEnabled(enable); if (enable) { if (btn.getBackground() != null) { btn.getBackground().clearColorFilter(); } } else { if (btn.getBackground() != null) { btn.getBackground().setColorFilter(android.graphics.Color.GRAY, android.graphics.PorterDuff.Mode.MULTIPLY); } } } }