From edaf7007d6feb533ff8ad75bd23926ba584325ca Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Tue, 30 Sep 2025 16:03:16 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E8=A7=A6=E5=8F=91=E5=93=8D?= =?UTF-8?q?=E5=BA=94=E6=A8=A1=E5=9D=97=E5=B7=B2=E5=9F=BA=E6=9C=AC=E5=AE=8C?= =?UTF-8?q?=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- positions/build.properties | 4 +- .../positions/adapters/PositionAdapter.java | 280 ++++++++++-------- .../positions/models/PositionTaskModel.java | 10 + .../positions/views/PositionTaskListView.java | 179 +++++------ .../src/main/res/drawable/bg_bingo_dot.xml | 8 + .../src/main/res/layout/item_position.xml | 60 ---- .../main/res/layout/item_position_edit.xml | 2 +- .../main/res/layout/item_position_simple.xml | 2 +- .../res/layout/item_position_task_simple.xml | 26 +- 9 files changed, 282 insertions(+), 289 deletions(-) create mode 100644 positions/src/main/res/drawable/bg_bingo_dot.xml delete mode 100644 positions/src/main/res/layout/item_position.xml diff --git a/positions/build.properties b/positions/build.properties index 128b8f3..f0dc16e 100644 --- a/positions/build.properties +++ b/positions/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Tue Sep 30 06:43:35 GMT 2025 +#Tue Sep 30 08:01:34 GMT 2025 stageCount=3 libraryProject= baseVersion=15.0 publishVersion=15.0.2 -buildCount=39 +buildCount=47 baseBetaVersion=15.0.3 diff --git a/positions/src/main/java/cc/winboll/studio/positions/adapters/PositionAdapter.java b/positions/src/main/java/cc/winboll/studio/positions/adapters/PositionAdapter.java index a143fc0..19d7d26 100644 --- a/positions/src/main/java/cc/winboll/studio/positions/adapters/PositionAdapter.java +++ b/positions/src/main/java/cc/winboll/studio/positions/adapters/PositionAdapter.java @@ -3,7 +3,7 @@ package cc.winboll.studio.positions.adapters; /** * @Author ZhanGSKen&豆包大模型 * @Date 2025/09/29 20:25 - * @Describe 位置数据适配器(修复定时器:仅刷新实时距离,不干扰编辑中的任务) + * @Describe 位置数据适配器(修复定时器:仅刷新实时距离,不干扰编辑中的任务;优化任务触发通知) */ import android.content.Context; import android.os.Handler; @@ -42,7 +42,7 @@ public class PositionAdapter extends RecyclerView.Adapter mPositionList; private final ArrayList mAllPositionTasks; private final Context mContext; @@ -50,8 +50,11 @@ public class PositionAdapter extends RecyclerView.Adapter> mPositionTaskMap; - // 关键新增:存储“位置ID → 距离TextView”的映射(仅包含当前可见的列表项) private final Map mVisibleDistanceViews = new HashMap<>(); + // 新增1:存储“位置ID→列表索引”映射(快速定位位置项,避免遍历) + private final Map mPositionIdToIndexMap = new HashMap<>(); + // 新增2:主线程Handler(确保UI更新在主线程,避免异常) + private final Handler mUiHandler = new Handler(Looper.getMainLooper()); // 接口回调(不变) public interface OnDeleteClickListener { @@ -70,7 +73,7 @@ public class PositionAdapter extends RecyclerView.Adapter positionList, ArrayList allPositionTasks) { this.mContext = context; this.mPositionList = (positionList != null) ? positionList : new ArrayList(); @@ -89,9 +92,11 @@ public class PositionAdapter extends RecyclerView.Adapter entry : mVisibleDistanceViews.entrySet()) { - String positionId = entry.getKey(); // 当前可见项的位置ID - TextView distanceView = entry.getValue(); // 要更新的距离文本控件 + String positionId = entry.getKey(); + TextView distanceView = entry.getValue(); - // 根据位置ID找到对应的PositionModel PositionModel targetModel = null; for (PositionModel model : mPositionList) { if (positionId.equals(model.getPositionId())) { @@ -149,7 +147,6 @@ public class PositionAdapter extends RecyclerView.Adapter= 0 && position < mPositionList.size()) { String positionId = mPositionList.get(position).getPositionId(); mVisibleDistanceViews.remove(positionId); + // 移除已回收位置的索引映射(避免内存泄漏) + mPositionIdToIndexMap.remove(positionId); } - // 清理任务列表资源(不变) if (holder instanceof SimpleViewHolder) { ((SimpleViewHolder) holder).ptlvSimpleTasks.clearData(); ((SimpleViewHolder) holder).ptlvSimpleTasks.setOnTaskUpdatedListener(null); @@ -266,17 +257,13 @@ public class PositionAdapter extends RecyclerView.Adapter matchedTasks = getSafeTasks(currentPosId); holder.ptlvSimpleTasks.clearData(); @@ -311,30 +297,28 @@ public class PositionAdapter extends RecyclerView.Adapter matchedTasks = getSafeTasks(currentPosId); holder.ptlvEditTasks.clearData(); @@ -403,52 +386,51 @@ public class PositionAdapter extends RecyclerView.Adapter currentTasks = getSafeTasks(currentPosId); - currentTasks.add(newTask); - mPositionTaskMap.put(currentPosId, new ArrayList(currentTasks)); - mAllPositionTasks.add(newTask); + ArrayList currentTasks = getSafeTasks(currentPosId); + currentTasks.add(newTask); + mPositionTaskMap.put(currentPosId, new ArrayList(currentTasks)); + mAllPositionTasks.add(newTask); - holder.ptlvEditTasks.clearData(); - holder.ptlvEditTasks.init(currentTasks, currentPosId); - holder.ptlvEditTasks.setViewStatus(PositionTaskListView.VIEW_MODE_EDIT); - Toast.makeText(mContext, "已新增1个任务(绑定当前位置)", Toast.LENGTH_SHORT).show(); - } - }); - } + holder.ptlvEditTasks.clearData(); + holder.ptlvEditTasks.init(currentTasks, currentPosId); + holder.ptlvEditTasks.setViewStatus(PositionTaskListView.VIEW_MODE_EDIT); + Toast.makeText(mContext, "已新增1个任务(绑定当前位置)", Toast.LENGTH_SHORT).show(); + } + }); + } - // 工具方法:绑定实时距离(逻辑不变,仅负责文本更新,不影响其他控件) - private void bindRealDistance(TextView distanceView, PositionModel model) { - if (!model.isEnableRealPositionDistance()) { - distanceView.setText("实时距离:未启用"); - distanceView.setTextColor(mContext.getResources().getColor(R.color.colorGrayText)); - return; - } + // 工具方法:绑定实时距离(不变) + private void bindRealDistance(TextView distanceView, PositionModel model) { + if (!model.isEnableRealPositionDistance()) { + distanceView.setText("实时距离:未启用"); + distanceView.setTextColor(mContext.getResources().getColor(R.color.colorGrayText)); + return; + } - if (mCurrentGpsPosition == null) { + if (mCurrentGpsPosition == null) { distanceView.setText("实时距离:等待GPS定位"); distanceView.setTextColor(mContext.getResources().getColor(R.color.colorGrayText)); return; @@ -456,6 +438,8 @@ public class PositionAdapter extends RecyclerView.Adapter getSafeTasks(String positionId) { +// ---------------------- 核心优化:bingoTask 任务触发通知逻辑(替换 notifyDataSetChanged()) ---------------------- + private void bingoTask(PositionModel model, int distanceM) { +// 1. 标记是否有任务触发(避免无变化时无效更新) + boolean hasTaskTriggered = false; +// 2. 记录当前位置ID(后续精准定位列表项) + final String targetPosId = model.getPositionId(); + +// 遍历当前位置的任务,判断是否触发 + for (PositionTaskModel task : mAllPositionTasks) { + if (targetPosId.equals(task.getPositionId())) { +// 暂存旧状态(避免重复触发更新) + boolean oldBingoState = task.isBingo(); + boolean newBingoState = false; + +// 根据任务条件判断新触发状态 + if (task.isGreaterThan()) { + newBingoState = distanceM > task.getDiscussDistance(); + } else if (task.isLessThan()) { + newBingoState = distanceM < task.getDiscussDistance(); + } else { + newBingoState = true; + } + +// 仅当状态变化时,才更新任务状态并标记需要通知 + if (newBingoState != oldBingoState) { + task.setIsBingo(newBingoState); + hasTaskTriggered = true; + } + } + } + +// 3. 仅当有任务触发且状态变化时,才执行精准更新(避免全局刷新) + if (hasTaskTriggered) { +// 切换到主线程更新UI(解决子线程更新异常) + mUiHandler.post(new Runnable() { + @Override + public void run() { +// 从映射表快速获取位置索引(避免遍历列表,提升效率) + Integer targetPosIndex = mPositionIdToIndexMap.get(targetPosId); + if (targetPosIndex != null && targetPosIndex >= 0 && targetPosIndex < mPositionList.size()) { +// 精准更新单个位置项(仅刷新该位置的任务列表,不干扰其他项) + notifyItemChanged(targetPosIndex); + } + } + }); + } + } + +// 工具方法:安全获取任务列表(不变) + private ArrayList getSafeTasks(String positionId) { if (!mPositionTaskMap.containsKey(positionId)) { - mPositionTaskMap.put(positionId, new ArrayList()); + mPositionTaskMap.put(positionId, new ArrayList()); } return mPositionTaskMap.get(positionId); } - // 对外API:新增位置(不变) +// 对外API:新增位置(补充索引映射更新) public void addPosition(PositionModel model) { if (model == null) return; String validPosId = model.getPositionId(); mPositionList.add(model); +// 新增:添加新位置的索引映射(索引为列表最后一位) + mPositionIdToIndexMap.put(validPosId, mPositionList.size() - 1); + if (!mPositionTaskMap.containsKey(validPosId)) { - mPositionTaskMap.put(validPosId, new ArrayList()); + mPositionTaskMap.put(validPosId, new ArrayList()); } notifyItemInserted(mPositionList.size() - 1); } - // 对外API:删除位置(不变,补充距离缓存清理) +// 对外API:删除位置(补充索引映射清理) public void removePosition(int position) { if (position < 0 || position >= mPositionList.size()) return; PositionModel removedModel = mPositionList.get(position); String removedPosId = removedModel.getPositionId(); - // 1. 清理距离缓存(新增:移除已删除位置的距离TextView) +// 1. 清理距离缓存和索引映射(新增) mVisibleDistanceViews.remove(removedPosId); + mPositionIdToIndexMap.remove(removedPosId); - // 2. 清理全局任务列表和映射表(不变) - Iterator taskIterator = mAllPositionTasks.iterator(); +// 2. 重新同步剩余位置的索引映射(避免删除后索引错位) + for (int i = position; i < mPositionList.size(); i++) { + PositionModel remainingModel = mPositionList.get(i); + mPositionIdToIndexMap.put(remainingModel.getPositionId(), i); + } + +// 3. 清理全局任务列表和映射表(不变) + Iterator taskIterator = mAllPositionTasks.iterator(); while (taskIterator.hasNext()) { - PositionTaskModel task = taskIterator.next(); + PositionTaskModel task = (PositionTaskModel)taskIterator.next(); if (task != null && removedPosId.equals(task.getPositionId())) { taskIterator.remove(); } @@ -510,16 +552,16 @@ public class PositionAdapter extends RecyclerView.Adapter newPositionList) { if (newPositionList == null) return; mPositionList.clear(); mPositionList.addAll(newPositionList); - // 1. 清理距离缓存中无效的位置ID(新增:仅保留新列表中的位置) - Iterator distanceViewIter = mVisibleDistanceViews.keySet().iterator(); +// 1. 清理距离缓存中无效的位置ID(不变) + Iterator distanceViewIter = mVisibleDistanceViews.keySet().iterator(); while (distanceViewIter.hasNext()) { - String posId = distanceViewIter.next(); + String posId = (String)distanceViewIter.next(); boolean isPosExist = false; for (PositionModel model : newPositionList) { if (posId.equals(model.getPositionId())) { @@ -532,10 +574,10 @@ public class PositionAdapter extends RecyclerView.Adapter taskMapKeyIter = mPositionTaskMap.keySet().iterator(); +// 2. 清理任务映射表(不变) + Iterator taskMapKeyIter = mPositionTaskMap.keySet().iterator(); while (taskMapKeyIter.hasNext()) { - String posId = taskMapKeyIter.next(); + String posId = (String)taskMapKeyIter.next(); boolean isPosExist = false; for (PositionModel model : newPositionList) { if (posId.equals(model.getPositionId())) { @@ -548,18 +590,21 @@ public class PositionAdapter extends RecyclerView.Adapter()); + mPositionTaskMap.put(posId, new ArrayList()); } } notifyDataSetChanged(); } - // 对外API:批量切换简单视图(不变) +// 对外API:批量切换简单视图(不变) public void switchAllToSimpleView() { for (PositionModel model : mPositionList) { model.setIsSimpleView(true); @@ -567,18 +612,17 @@ public class PositionAdapter extends RecyclerView.Adapter getPositionList() { - return new ArrayList(mPositionList); +// 对外API:获取位置列表(不变) + public ArrayList getPositionList() { + return new ArrayList(mPositionList); } - // ---------------------- ViewHolder 定义(核心补充:编辑视图的距离TextView) ---------------------- - // 简单视图Holder(不变) +// ---------------------- ViewHolder 定义(不变) ---------------------- public static class SimpleViewHolder extends RecyclerView.ViewHolder { TextView tvSimpleLongitude; TextView tvSimpleLatitude; TextView tvSimpleMemo; - TextView tvSimpleRealDistance; // 简单视图-距离文本 + TextView tvSimpleRealDistance; PositionTaskListView ptlvSimpleTasks; public SimpleViewHolder(@NonNull View itemView) { @@ -591,7 +635,6 @@ public class PositionAdapter extends RecyclerView.Adapter * @Date 2025/09/30 08:09 - * @Describe 位置任务列表视图(支持简单/编辑模式,确保任务修改实时生效) + * @Describe 位置任务列表视图(支持简单/编辑模式,含 isBingo 红点标识) */ import android.content.Context; import android.util.AttributeSet; @@ -65,29 +65,21 @@ public class PositionTaskListView extends LinearLayout { // 初始化视图(绑定控件+设置布局) private void initView(Context context) { setOrientation(VERTICAL); - // 加载根布局(view_position_task_list.xml) LayoutInflater.from(context).inflate(R.layout.view_position_task_list, this, true); - // 绑定RecyclerView并设置布局管理器 mRvTasks = (RecyclerView) findViewById(R.id.rv_position_tasks); mRvTasks.setLayoutManager(new LinearLayoutManager(context)); - // 初始化任务列表+适配器(强引用关联,确保数据同步) mTaskList = new ArrayList(); mTaskAdapter = new TaskListAdapter(mTaskList); mRvTasks.setAdapter(mTaskAdapter); - // 默认简单模式 mCurrentViewMode = VIEW_MODE_SIMPLE; } // ---------------------- 对外API ---------------------- - /** - * 初始化任务列表(仅首次空列表时加载,避免覆盖修改后数据) - */ public void init(ArrayList taskList, String positionId) { this.mBindPositionId = positionId; - // 仅内部列表为空时加载外部数据 if (this.mTaskList.isEmpty()) { ArrayList matchedTasks = new ArrayList(); if (taskList != null && !taskList.isEmpty()) { @@ -103,9 +95,6 @@ public class PositionTaskListView extends LinearLayout { mTaskAdapter.notifyDataSetChanged(); } - /** - * 设置视图模式(简单/编辑) - */ public void setViewStatus(int viewMode) { if (viewMode != VIEW_MODE_SIMPLE && viewMode != VIEW_MODE_EDIT) { return; @@ -114,23 +103,14 @@ public class PositionTaskListView extends LinearLayout { mTaskAdapter.notifyDataSetChanged(); } - /** - * 设置任务修改回调 - */ public void setOnTaskUpdatedListener(OnTaskUpdatedListener listener) { this.mOnTaskUpdatedListener = listener; } - /** - * 获取当前任务列表(返回副本,避免外部修改污染) - */ public ArrayList getAllTasks() { return new ArrayList(mTaskList); } - /** - * 清空任务数据(避免RecyclerView复用残留) - */ public void clearData() { mTaskList.clear(); if (mTaskAdapter != null && mTaskAdapter.mData != null) { @@ -140,9 +120,6 @@ public class PositionTaskListView extends LinearLayout { mBindPositionId = null; } - /** - * 主动触发任务同步(供外部强制同步数据) - */ public void triggerTaskSync() { if (mOnTaskUpdatedListener != null && mBindPositionId != null) { mOnTaskUpdatedListener.onTaskUpdated(mBindPositionId, new ArrayList(mTaskList)); @@ -150,9 +127,6 @@ public class PositionTaskListView extends LinearLayout { } // ---------------------- 内部工具方法 ---------------------- - /** - * 校验任务是否与当前位置匹配 - */ private boolean isTaskMatchedWithPosition(PositionTaskModel task) { if (task == null || mBindPositionId == null || mBindPositionId.trim().isEmpty()) { return false; @@ -160,53 +134,63 @@ public class PositionTaskListView extends LinearLayout { return mBindPositionId.equals(task.getPositionId()); } - // ---------------------- 内部Adapter:任务列表适配器(核心修改:确保修改生效) ---------------------- + // ---------------------- 内部Adapter:适配 isBingo 红点(核心调整) ---------------------- private class TaskListAdapter extends RecyclerView.Adapter { - // 适配器数据源(与外部mTaskList强引用,确保数据实时同步) private final List mData; public TaskListAdapter(List data) { this.mData = data; } - // 获取列表项数量(空列表显示1个“空提示”项) @Override public int getItemCount() { return mData.isEmpty() ? 1 : mData.size(); } - // 区分视图类型(0=空提示,1=任务项) + // 调整:根据“是否空列表”+“视图模式”区分视图类型(确保简单/编辑模式加载对应布局) @Override public int getItemViewType(int position) { - return mData.isEmpty() ? 0 : 1; + if (mData.isEmpty()) { + return 0; // 0=空提示 + } else { + return mCurrentViewMode; // 1=简单模式,2=编辑模式(复用视图模式常量) + } } - // 创建ViewHolder + // 调整:按视图类型加载布局(简单模式加载带红点的布局,编辑模式加载原有布局) @NonNull @Override public TaskViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { Context context = parent.getContext(); LayoutInflater inflater = LayoutInflater.from(context); + if (viewType == 0) { - // 空提示布局(item_task_empty.xml) + // 空提示布局 View emptyView = inflater.inflate(R.layout.item_task_empty, parent, false); return new EmptyViewHolder(emptyView); + } else if (viewType == VIEW_MODE_SIMPLE) { + // 简单模式布局(带 isBingo 红点) + View simpleTaskView = inflater.inflate(R.layout.item_position_task_simple, parent, false); + return new SimpleTaskViewHolder(simpleTaskView); } else { - // 任务项布局(item_task_content.xml) - View taskView = inflater.inflate(R.layout.item_task_content, parent, false); - return new TaskContentViewHolder(taskView); + // 编辑模式布局(原有布局不变) + View editTaskView = inflater.inflate(R.layout.item_task_content, parent, false); + return new TaskContentViewHolder(editTaskView); } } - // 绑定数据(核心:修复开关监听重复绑定+实时刷新) + // 调整:按视图类型绑定数据(简单模式绑定红点+文本,编辑模式绑定原有逻辑) @Override public void onBindViewHolder(@NonNull TaskViewHolder holder, int position) { + // 空提示处理(不变) if (holder instanceof EmptyViewHolder) { - // 空提示项无需绑定数据 + EmptyViewHolder emptyHolder = (EmptyViewHolder) holder; + TextView tvEmptyTip = (TextView) emptyHolder.itemView.findViewById(R.id.tv_task_empty_tip); + tvEmptyTip.setText(mCurrentViewMode == VIEW_MODE_EDIT ? "暂无任务,点击\"添加新任务\"创建" : "暂无启用的任务"); return; } - // 校验位置有效性(避免越界) + // 任务项有效性校验(不变) if (position >= mData.size()) { return; } @@ -215,16 +199,28 @@ public class PositionTaskListView extends LinearLayout { return; } - // 绑定任务数据 - final TaskContentViewHolder contentHolder = (TaskContentViewHolder) holder; - bindTaskData(contentHolder, task, position); + // 简单模式:绑定红点(isBingo)和文本数据 + if (holder instanceof SimpleTaskViewHolder) { + SimpleTaskViewHolder simpleHolder = (SimpleTaskViewHolder) holder; + // 绑定任务描述 + simpleHolder.tvSimpleTaskDesc.setText(String.format("任务:%s", task.getTaskDescription())); + // 绑定距离条件 + String distanceCond = task.isGreaterThan() ? "大于" : "小于"; + simpleHolder.tvSimpleDistanceCond.setText(String.format("条件:距离 %s %d 米", distanceCond, task.getDiscussDistance())); + // 绑定启用状态 + simpleHolder.tvSimpleIsEnable.setText(task.isEnable() ? "状态:已启用" : "状态:已禁用"); + // 核心:根据 isBingo 控制红点显示(true=显示,false=隐藏) + simpleHolder.vBingoDot.setVisibility(task.isBingo() ? View.VISIBLE : View.GONE); + } + // 编辑模式:沿用原有绑定逻辑(不变) + else if (holder instanceof TaskContentViewHolder) { + TaskContentViewHolder contentHolder = (TaskContentViewHolder) holder; + bindTaskData(contentHolder, task, position); + } } - /** - * 绑定任务具体数据(核心修复:开关监听去重+修改后实时刷新) - */ + // ---------------------- 原有编辑模式绑定逻辑(完全不变) ---------------------- private void bindTaskData(final TaskContentViewHolder holder, final PositionTaskModel task, final int position) { - // 1. 绑定基础信息(描述、距离条件、启用状态) String taskDesc = (task.getTaskDescription() == null) ? "未设置描述" : task.getTaskDescription(); holder.tvTaskDesc.setText(String.format("任务:%s", taskDesc)); @@ -232,21 +228,18 @@ public class PositionTaskListView extends LinearLayout { holder.tvTaskDistance.setText(String.format("条件:%s %d 米", distanceCondition, task.getDiscussDistance())); holder.cbTaskEnable.setChecked(task.isEnable()); - holder.cbTaskEnable.setEnabled(mCurrentViewMode == VIEW_MODE_EDIT); // 仅编辑模式可点击 + holder.cbTaskEnable.setEnabled(mCurrentViewMode == VIEW_MODE_EDIT); - // 2. 编辑模式处理(核心:修复开关监听重复绑定+修改同步) if (mCurrentViewMode == VIEW_MODE_EDIT) { holder.btnEditTask.setVisibility(View.VISIBLE); holder.btnDeleteTask.setVisibility(View.VISIBLE); - // (1)删除按钮逻辑 holder.btnDeleteTask.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - mData.remove(position); // 移除数据源中任务 - notifyItemRemoved(position); // 刷新列表(移除项) - notifyItemRangeChanged(position, mData.size()); // 刷新后续项索引 - // 同步通知外部 + mData.remove(position); + notifyItemRemoved(position); + notifyItemRangeChanged(position, mData.size()); if (mOnTaskUpdatedListener != null && mBindPositionId != null) { mOnTaskUpdatedListener.onTaskUpdated(mBindPositionId, new ArrayList(mData)); } @@ -254,7 +247,6 @@ public class PositionTaskListView extends LinearLayout { } }); - // (2)修改按钮逻辑(弹窗编辑) holder.btnEditTask.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -262,45 +254,37 @@ public class PositionTaskListView extends LinearLayout { } }); - // (核心修复1:绑定新监听前先移除旧监听,避免重复触发) holder.cbTaskEnable.setOnCheckedChangeListener(null); holder.cbTaskEnable.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - task.setIsEnable(isChecked); // 直接修改数据源中任务的启用状态 - notifyItemChanged(position); // 实时刷新当前项(显示最新状态) - // 同步通知外部 + task.setIsEnable(isChecked); + notifyItemChanged(position); if (mOnTaskUpdatedListener != null && mBindPositionId != null) { mOnTaskUpdatedListener.onTaskUpdated(mBindPositionId, new ArrayList(mData)); } } }); } else { - // 简单模式:隐藏编辑按钮+移除监听 holder.btnEditTask.setVisibility(View.GONE); holder.btnDeleteTask.setVisibility(View.GONE); holder.cbTaskEnable.setOnCheckedChangeListener(null); } } - /** - * 任务编辑弹窗(核心修复2:修改后实时刷新+同步数据) - */ + // ---------------------- 原有编辑弹窗逻辑(完全不变) ---------------------- private void showTaskEditDialog(final PositionTaskModel task, final int position) { final Context context = getContext(); - // 加载弹窗布局(dialog_edit_task.xml) View dialogView = LayoutInflater.from(context).inflate(R.layout.dialog_edit_task, null); - // 绑定弹窗控件 final EditText etEditDesc = (EditText) dialogView.findViewById(R.id.et_edit_task_desc); final RadioGroup rgDistanceCondition = (RadioGroup) dialogView.findViewById(R.id.rg_distance_condition); final EditText etEditDistance = (EditText) dialogView.findViewById(R.id.et_edit_distance); Button btnCancel = (Button) dialogView.findViewById(R.id.btn_dialog_cancel); Button btnSave = (Button) dialogView.findViewById(R.id.btn_dialog_save); - // 初始化弹窗数据(显示当前任务信息) etEditDesc.setText(task.getTaskDescription()); - etEditDesc.setSelection(etEditDesc.getText().length()); // 光标定位到末尾 + etEditDesc.setSelection(etEditDesc.getText().length()); if (task.isGreaterThan()) { rgDistanceCondition.check(R.id.rb_greater_than); @@ -310,13 +294,11 @@ public class PositionTaskListView extends LinearLayout { etEditDistance.setText(String.valueOf(task.getDiscussDistance())); - // 创建并显示弹窗 final android.app.AlertDialog dialog = new android.app.AlertDialog.Builder(context) .setView(dialogView) .create(); dialog.show(); - // 取消按钮:关闭弹窗(不保存) btnCancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -324,11 +306,9 @@ public class PositionTaskListView extends LinearLayout { } }); - // 保存按钮:校验+更新+同步(核心修复:实时刷新列表) btnSave.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - // 1. 输入校验 String newDesc = etEditDesc.getText().toString().trim(); String distanceStr = etEditDistance.getText().toString().trim(); @@ -340,7 +320,7 @@ public class PositionTaskListView extends LinearLayout { int newDistance; try { newDistance = Integer.parseInt(distanceStr); - if (newDistance < 1) { // 距离最小为1米,避免无效值 + if (newDistance < 1) { Toast.makeText(context, "距离不能小于1米", Toast.LENGTH_SHORT).show(); return; } @@ -349,69 +329,66 @@ public class PositionTaskListView extends LinearLayout { return; } - // 2. 更新任务数据(直接修改数据源中的任务对象,强引用同步) task.setTaskDescription(newDesc); task.setDiscussDistance(newDistance); - // 更新距离条件(大于/小于) boolean isGreater = rgDistanceCondition.getCheckedRadioButtonId() == R.id.rb_greater_than; task.setIsGreaterThan(isGreater); - // 强制绑定当前位置ID,避免任务串位 task.setPositionId(mBindPositionId); - // 3. 核心修复:实时刷新当前任务项,确保修改后立即显示 notifyItemChanged(position); - // 4. 同步通知外部Adapter更新全局数据 if (mOnTaskUpdatedListener != null && mBindPositionId != null) { mOnTaskUpdatedListener.onTaskUpdated(mBindPositionId, new ArrayList(mData)); } - // 5. 关闭弹窗并提示 dialog.dismiss(); Toast.makeText(context, "任务已更新", Toast.LENGTH_SHORT).show(); } }); } - // ---------------------- ViewHolder 定义(内部类,绑定布局控件) ---------------------- - /** - * 基础ViewHolder(抽象类,统一父类型) - */ + // ---------------------- ViewHolder 定义(新增简单模式 Holder,适配红点) ---------------------- + // 基础抽象 ViewHolder(不变) public abstract class TaskViewHolder extends RecyclerView.ViewHolder { public TaskViewHolder(@NonNull View itemView) { super(itemView); } } - /** - * 空提示ViewHolder(绑定“无任务”提示布局 item_task_empty.xml) - */ + // 空提示 Holder(不变) public class EmptyViewHolder extends TaskViewHolder { public EmptyViewHolder(@NonNull View itemView) { super(itemView); - // 根据当前视图模式修改提示文本 - TextView tvEmptyTip = (TextView) itemView.findViewById(R.id.tv_task_empty_tip); - if (mCurrentViewMode == VIEW_MODE_EDIT) { - tvEmptyTip.setText("暂无任务,点击\"添加新任务\"创建"); - } else { - tvEmptyTip.setText("暂无启用的任务"); - } } } - /** - * 任务内容ViewHolder(绑定任务项布局 item_task_content.xml) - */ + // 新增:简单模式 Holder(绑定带红点的布局控件) + public class SimpleTaskViewHolder extends TaskViewHolder { + TextView tvSimpleTaskDesc; // 任务描述 + TextView tvSimpleDistanceCond;// 距离条件 + TextView tvSimpleIsEnable; // 启用状态 + View vBingoDot; // isBingo 红点控件 + + public SimpleTaskViewHolder(@NonNull View itemView) { + super(itemView); + // 绑定简单模式布局中的控件(与 item_task_simple.xml 完全对应) + tvSimpleTaskDesc = itemView.findViewById(R.id.tv_simple_task_desc); + tvSimpleDistanceCond = itemView.findViewById(R.id.tv_simple_distance_cond); + tvSimpleIsEnable = itemView.findViewById(R.id.tv_simple_is_enable); + vBingoDot = itemView.findViewById(R.id.v_bingo_dot); + } + } + + // 编辑模式 Holder(原有逻辑,完全不变) public class TaskContentViewHolder extends TaskViewHolder { - TextView tvTaskDesc; // 任务描述 - TextView tvTaskDistance; // 距离条件(如“大于 100 米”) - CompoundButton cbTaskEnable; // 任务启用/禁用开关 - Button btnEditTask; // 编辑任务按钮 - Button btnDeleteTask; // 删除任务按钮 + TextView tvTaskDesc; + TextView tvTaskDistance; + CompoundButton cbTaskEnable; + Button btnEditTask; + Button btnDeleteTask; public TaskContentViewHolder(@NonNull View itemView) { super(itemView); - // 绑定布局控件(与 item_task_content.xml 中的ID严格对应) tvTaskDesc = (TextView) itemView.findViewById(R.id.tv_task_desc); tvTaskDistance = (TextView) itemView.findViewById(R.id.tv_task_distance); cbTaskEnable = (CompoundButton) itemView.findViewById(R.id.cb_task_enable); diff --git a/positions/src/main/res/drawable/bg_bingo_dot.xml b/positions/src/main/res/drawable/bg_bingo_dot.xml new file mode 100644 index 0000000..248bd1b --- /dev/null +++ b/positions/src/main/res/drawable/bg_bingo_dot.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/positions/src/main/res/layout/item_position.xml b/positions/src/main/res/layout/item_position.xml deleted file mode 100644 index 3f9c77e..0000000 --- a/positions/src/main/res/layout/item_position.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - -