禁止Cell被选中之后进入高亮状态

本文介绍了如何在iOS应用中通过自定义方式实现类似Android的复选框功能,并解决了选中状态下的背景高亮问题,提供了具体的代码实现和优化方案。

iOS没有像Android那样的原生复选框SDK,只能自定义,自定义最好的办法就是把tableView中得cell设置为可编辑的,代码如下:


    UITableViewCell *cell;

   if (indexPath.section ==0) {

        cell=[self.batteryAlertTableViewdequeueReusableCellWithIdentifier:@"ItemCell"];

       if (cell ==nil) {

            cell=[[UITableViewCellalloc]initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:@"ItemCell"];

        }

        NSMutableArray *tempobject=[[NSUserDefaultsstandardUserDefaults]objectForKey:@"batteryAlertMulti"];

       for (NSObject *rowin tempobject)

        {

           NSNumber *tempNum = (NSNumber*) row;

           int rownumber = [tempNum intValue];

           NSInteger selectedIndex = rownumber;

           NSIndexPath *selectedIndexPath = [NSIndexPathindexPathForRow:selectedIndex inSection:0];

            [self.batteryAlertTableViewselectRowAtIndexPath:selectedIndexPath animated:NOscrollPosition:UITableViewScrollPositionNone];

        }

        cell.textLabel.text = [self.dataArrayobjectAtIndex:indexPath.row];

        cell.textLabel.textColor=[UIColorwhiteColor];

        //[cell setSelectionStyle:UITableViewCellSelectionStyleNone];

    }


这样当你选中多个cell 的时候 ,这些cell的颜色都会变得高亮,非常的影响用户的体验,最好的解决办法是在设置cell属性时加上如下代码:

    //去除cell在选中时的高亮白色

    cell.selectedBackgroundView=[[UIViewalloc]initWithFrame:cell.frame];

    cell.selectedBackgroundView.backgroundColor=[UIColorclearColor];

    

   return cell;

}


前一段代码可以参考解决IOS复选框的问题,后一段代码解决选中后的背景高亮问题,在处理IOStableView中得复选框这类问题非常的实用!
<template> <div class="bg-gray-50 p-6"> <div class="max-w-7xl mx-auto"> <h1 class="text-2xl font-bold text-gray-800 mb-6">交叉决策表</h1> <div class="table-container"> <table id="decision-table" class="decision-table"> <thead id="table-header"> <tr v-for="(headerRow, rowIndex) in tableData.headers" :key="rowIndex" class="table-header" > <th v-for="(cell, colIndex) in headerRow" :key="colIndex" :colspan="cell.colspan" :rowspan="cell.rowspan" :data-isHeader="cell.isHeader" class="header-cell" scope="col" @contextmenu.prevent="showContextMenu($event, { isHeader: true, rowIndex: rowIndex, colIndex: colIndex, cell:cell })" > {{ cell.text }} </th> </tr> </thead> <tbody id="table-body"> <tr v-for="(row, rowIndex) in tableData.rows" :key="rowIndex" > <td v-for="(cell, colIndex) in row" :key="colIndex" :colspan="cell.colspan" :rowspan="cell.rowspan" :data-isHeader="cell.isHeader" :class="{ 'header-cell merged-cell': cell.isHeader, 'data-cell': !cell.isHeader, 'highlight-cell': isCellHighlighted(rowIndex, colIndex) }" :data-scope="cell.isHeader ? 'row' : 'data'" @contextmenu.prevent="cell.isHeader && showContextMenu($event, { isHeader: true, rowIndex: rowIndex, colIndex: colIndex })" > {{ cell.text }} </td> </tr> </tbody> </table> </div> <div class="mt-6 text-sm text-gray-500"> <p>提示:在表头单元格上右键点击可打开上下文菜单,进行行和列的添加/删除操作。</p> </div> </div> <!-- 上下文菜单 --> <div id="context-menu" :class="contextMenuClass" :style="{ left: contextMenuLeft + 'px', top: contextMenuTop + 'px' }" > <div class="context-menu-item" @click="executeAction('add-row')"> <i class="fa fa-plus-circle mr-2"></i>新增行 </div> <div class="context-menu-item" @click="executeAction('delete-row')"> <i class="fa fa-minus-circle mr-2"></i>删除行 </div> <div class="context-menu-separator"></div> <div class="context-menu-item" @click="executeAction('add-column')"> <i class="fa fa-plus-square mr-2"></i>新增列 </div> <div class="context-menu-item" @click="executeAction('delete-column')"> <i class="fa fa-minus-square mr-2"></i>删除列 </div> </div> </div> </template> <script> export default { data() { return { // 表格数据模型 tableData: { headers: [ // 第一级表头 [ { text: '', colspan: 2, rowspan: 2, isHeader: true }, { text: '维度A', colspan: 6, rowspan: 1, isHeader: true } ], // 第二级表头 [ { text: '指标A', colspan: 2, rowspan: 1, isHeader: true }, { text: '指标B', colspan: 2, rowspan: 1, isHeader: true }, { text: '指标C', colspan: 2, rowspan: 1, isHeader: true } ], // 第三级表头 [ { text: '部门', colspan: 1, rowspan: 1, isHeader: true }, { text: '业务线', colspan: 1, rowspan: 1, isHeader: true }, { text: '目标', colspan: 1, rowspan: 1, isHeader: true }, { text: '实际', colspan: 1, rowspan: 1, isHeader: true }, { text: '目标', colspan: 1, rowspan: 1, isHeader: true }, { text: '实际', colspan: 1, rowspan: 1, isHeader: true }, { text: '目标', colspan: 1, rowspan: 1, isHeader: true }, { text: '实际', colspan: 1, rowspan: 1, isHeader: true } ] ], rows: [ // 第一行数据 [ { text: '0002 设计部', colspan: 1, rowspan: 2, isHeader: true }, { text: '设计1部', colspan: 1, rowspan: 1, isHeader: true }, { text: '6%', colspan: 1, rowspan: 1 }, { text: '6%', colspan: 1, rowspan: 1 }, { text: '5%', colspan: 1, rowspan: 1 }, { text: '3%', colspan: 1, rowspan: 1 }, { text: '4%', colspan: 1, rowspan: 1 }, { text: '4%', colspan: 1, rowspan: 1 } ], // 第二行数据 [ { text: '设计2部', colspan: 1, rowspan: 1, isHeader: true }, { text: '10%', colspan: 1, rowspan: 1 }, { text: '8%', colspan: 1, rowspan: 1 }, { text: '16%', colspan: 1, rowspan: 1 }, { text: '16%', colspan: 1, rowspan: 1 }, { text: '19%', colspan: 1, rowspan: 1 }, { text: '18%', colspan: 1, rowspan: 1 } ] ] }, // 当前选中的单元格信息 currentCellInfo: null, // 上下文菜单位置 contextMenuLeft: 0, contextMenuTop: 0, // 是否显示上下文菜单 showContextMenuFlag: false, angelData:[] }; }, computed: { // 计算上下文菜单的显示状态 contextMenuClass() { // console.log("执行contextMenuClass") return this.showContextMenuFlag ? 'context-menu' : 'context-menu hidden'; } }, created() { this.angelData = this.getAngelTable(); console.log("this.angelData",this.angelData); }, watch: { tableData(newData,oldData){ } }, methods: { // 检查单元格是否被高亮 isCellHighlighted(rowIndex, colIndex) { if (!this.currentCellInfo) return false; return ( this.currentCellInfo.rowIndex === rowIndex && this.currentCellInfo.colIndex === colIndex ); }, // 显示上下文菜单 showContextMenu(event, cellInfo) { this.currentCellInfo = cellInfo; this.contextMenuLeft = event.pageX; this.contextMenuTop = event.pageY; this.showContextMenuFlag = true; console.log('右键菜单点击',cellInfo); // 新增这行 }, // 执行菜单操作 executeAction(action) { // console.log('执行菜单操作'); console.log(this.getAngelTable()) switch (action) { case 'add-row': this.addRow(); break; case 'delete-row': this.deleteRow(); break; case 'add-column': this.addColumn(); break; case 'delete-column': this.deleteColumn(); break; } this.showContextMenuFlag = false; this.currentCellInfo = null; }, // 新增行 addRow() { console.log("新增行") if (!this.currentCellInfo || !this.currentCellInfo.isHeader) return; const { rowIndex } = this.currentCellInfo; const isHeaderRow = this.currentCellInfo.isHeader && this.currentCellInfo.rowIndex < this.tableData.headers.length; if (isHeaderRow) { // 新增表头行(简化处理) alert('新增表头行功能需要更复杂的逻辑处理,请参考数据行添加方式实现'); } else { // 新增数据行 const newRow = []; // 获取上一行的单元格数量 const prevRowCells = this.tableData.rows[rowIndex] || []; // 创建新行的单元格 prevRowCells.forEach(cell => { // 如果是合并的单元格且跨越多行,需要调整 if (cell.rowspan > 1) { // 减少上一行合并单元格的rowspan cell.rowspan--; // 如果当前行是合并单元格的第一行,不添加新单元格 if (rowIndex === 0 || prevRowCells || !prevRowCells[prevRowCells.indexOf(cell)].skip) { return; } } // 创建新单元格,复制上一行的结构 newRow.push({ text: '', colspan: cell.colspan, rowspan: cell.rowspan, isHeader: cell.isHeader }); }); // 插入新行 this.tableData.rows.splice(rowIndex + 1, 0, newRow); } }, // 删除行 deleteRow() { if (!this.currentCellInfo || !this.currentCellInfo.isHeader) return; const { rowIndex } = this.currentCellInfo; const isHeaderRow = this.currentCellInfo.isHeader && this.currentCellInfo.rowIndex < this.tableData.headers.length; if (isHeaderRow) { // 删除表头行(简化处理) alert('删除表头行功能需要更复杂的逻辑处理,请参考数据行删除方式实现'); } else { // 删除数据行 if (this.tableData.rows.length <= 1) { alert('至少需要保留一行数据'); return; } // 检查是否有合并到当前行的单元格 this.tableData.rows.forEach((row, rIndex) => { if (rIndex >= rowIndex) return; row.forEach(cell => { if (cell.rowspan > 1 && rIndex + cell.rowspan > rowIndex) { // 调整合并单元格的rowspan cell.rowspan--; } }); }); // 删除行 this.tableData.rows.splice(rowIndex, 1); } }, // 新增列 addColumn() { if (!this.currentCellInfo || !this.currentCellInfo.isHeader) return; const { colIndex } = this.currentCellInfo; // 更新表头 this.tableData.headers.forEach((headerRow) => { for (let i = 0; i < headerRow.length; i++) { const cell = headerRow[i]; // 如果当前单元格包含插入点,增加其colspan if (cell.colspan > 1 && i <= colIndex && i + cell.colspan > colIndex) { cell.colspan++; break; } // 如果到达插入位置,插入新单元格 if (i === colIndex) { headerRow.splice(i + 1, 0, { text: headerRow === this.tableData.headers[2] ? '新增' : '', colspan: 1, rowspan: 1, isHeader: true }); break; } } }); // 更新数据行 this.tableData.rows.forEach(row => { for (let i = 0; i < row.length; i++) { const cell = row[i]; // 如果当前单元格包含插入点,增加其colspan if (cell.colspan > 1 && i <= colIndex && i + cell.colspan > colIndex) { cell.colspan++; break; } // 如果到达插入位置,插入新单元格 if (i === colIndex) { row.splice(i + 1, 0, { text: '', colspan: 1, rowspan: 1, isHeader: cell.isHeader }); break; } } }); }, // 删除列 deleteColumn() { if (!this.currentCellInfo || !this.currentCellInfo.isHeader) return; const { colIndex } = this.currentCellInfo; // 检查是否可以删除列 const totalColumns = this.countTotalColumns(); if (totalColumns <= 2) { // 至少保留部门和业务线两列 alert('至少需要保留两列'); return; } // 更新表头 this.tableData.headers.forEach((headerRow) => { let currentCol = 0; let i = 0; while (i < headerRow.length) { const cell = headerRow[i]; // 如果当前单元格包含要删除的列 if (currentCol <= colIndex && currentCol + cell.colspan > colIndex) { // 减少colspan cell.colspan--; // 如果colspan变为0,删除单元格 if (cell.colspan === 0) { headerRow.splice(i, 1); continue; } } currentCol += cell.colspan; i++; } }); // 更新数据行 this.tableData.rows.forEach(row => { let currentCol = 0; let i = 0; while (i < row.length) { const cell = row[i]; // 如果当前单元格包含要删除的列 if (currentCol <= colIndex && currentCol + cell.colspan > colIndex) { // 减少colspan cell.colspan--; // 如果colspan变为0,删除单元格 if (cell.colspan === 0) { row.splice(i, 1); continue; } } currentCol += cell.colspan; i++; } }); }, // 计算总列数 countTotalColumns() { if (!this.tableData.headers.length) return 0; let totalColumns = 0; this.tableData.headers[0].forEach(cell => { totalColumns += cell.colspan; }); return totalColumns; }, /** * 转换表格行数据为包含合并单元格信息的二维数组 * @param {Object} rows 表格行数据,每行包含columns属性(单元格数组) * @returns {Array<Array>} 二维数组,每个位置填充对应的合并单元格信息 */ getAngelTable() { const rows = [...this.tableData.headers,...this.tableData.rows]; // 存储所有解析后的单元格信息 const resolvedCells = []; // 记录每行已被占用的列(key:行号,value:被占用的列号集合) const occupiedCols = {}; // 遍历每行,计算每个单元格的位置 for (let currentRow = 0; currentRow < rows.length; currentRow++) { const row = rows[currentRow]; if (!row) continue; let currentCol = 0; // 当前行的起始列(从0开始) for (const cell of row) { // 计算当前单元格的startCol:跳过已被占用的列 while (this.isColumnOccupied(currentRow, currentCol, occupiedCols)) { currentCol++; } // 单元格的基本信息 const colSpan = cell.colspan; const rowSpan = cell.rowspan; const startRow = currentRow; const startCol = currentCol; const endRow = startRow + rowSpan - 1; const endCol = startCol + colSpan - 1; // 记录单元格信息 resolvedCells.push({ startRow, startCol, endRow, endCol // 可根据需要添加原单元格的其他属性 }); // 标记当前单元格覆盖的所有行和列为“已占用” this.markOccupiedColumns(startRow, endRow, startCol, endCol, occupiedCols); // 移动到下一个未被占用的列 currentCol = endCol + 1; } } // 计算表格的总行数和总列数 const totalRows = resolvedCells.length ? Math.max(...resolvedCells.map(cell => cell.endRow)) + 1 : 0; const totalCols = resolvedCells.length ? Math.max(...resolvedCells.map(cell => cell.endCol)) + 1 : 0; // 初始化二维数组并填充null const flatTable = []; for (let i = 0; i < totalRows; i++) { flatTable.push(new Array(totalCols).fill(null)); } // 填充每个单元格到其覆盖的所有位置 for (const cell of resolvedCells) { for (let r = cell.startRow; r <= cell.endRow; r++) { for (let c = cell.startCol; c <= cell.endCol; c++) { flatTable[r][c] = cell; } } } return flatTable; }, /** * 检查当前行的当前列是否被占用 * @param {number} row 行号 * @param {number} col 列号 * @param {Object} occupiedCols 存储每行被占用列的对象 * @returns {boolean} 是否被占用 */ isColumnOccupied(row, col, occupiedCols) { const occupied = occupiedCols[row] || new Set(); return occupied.has(col); }, /** * 标记单元格覆盖的所有行和列为“已占用” * @param {number} startRow 起始行 * @param {number} endRow 结束行(含) * @param {number} startCol 起始列 * @param {number} endCol 结束列(含) * @param {Object} occupiedCols 存储每行被占用列的对象 */ markOccupiedColumns(startRow, endRow, startCol, endCol, occupiedCols) { for (let r = startRow; r <= endRow; r++) { // 为当前行初始化占用列集合 if (!occupiedCols[r]) { occupiedCols[r] = new Set(); } const cols = occupiedCols[r]; // 添加当前单元格覆盖的列 for (let c = startCol; c <= endCol; c++) { cols.add(c); } } } }, mounted() { // 点击其他地方关闭菜单 document.addEventListener('click', () => { this.showContextMenuFlag = false; this.currentCellInfo = null; }); } }; </script> <style> table { width: 100%; max-width: 1000px; margin: 20px auto; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 14px; } /* 所有单元格显示边框 */ th, td { padding: 12px 15px; border: 1px solid #ccc; text-align: center; } /* 列表头(横向表头)样式 - 适用于任意数量的顶部表头行 */ th[scope="col"] { background-color: #4a90e2; /* 列表头蓝色 */ color: white; font-weight: bold; } /* 行表头(纵向表头)样式 - 适用于任意数量的左侧表头列 */ td[scope="row"] { background-color: #4a90e2; /* 行表头绿色 */ color: white; font-weight: bold; position: sticky; left: 0; z-index: 1; } /* 表头交叉区域(同时属于行列表头的单元格) */ th[scope="colgroup"] { background-color: #5cb85c; /* 交叉区域橙色 */ color: white; font-weight: bold; z-index: 2; } /* 响应式调整 */ @media screen and (max-width: 768px) { th, td { padding: 8px 10px; font-size: 13px; } } /* 上下文菜单样式 */ .context-menu { position: absolute; background-color: white; border: 1px solid #ccc; border-radius: 4px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); padding: 5px 0; z-index: 1000; } .context-menu-item { padding: 8px 15px; cursor: pointer; white-space: nowrap; } .context-menu-item:hover { background-color: #f5f5f5; } .context-menu-separator { height: 1px; background-color: #eee; margin: 5px 0; } .hidden { display: none; } .highlight-cell { background-color: #ffecb3 !important; } /* 上下文菜单容器 */ .context-menu { /* 核心:绝对定位,基于页面坐标定位 */ position: absolute; /* 确保菜单在最上层,避免被其他元素覆盖 */ z-index: 9999; /* 固定宽度,避免内容撑开导致位置偏移 */ width: 160px; /* 基础外观 */ background-color: #fff; border: 1px solid #e0e0e0; border-radius: 4px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15); /* 去除默认边距 */ margin: 0; padding: 4px 0; /* 避免选中菜单文本 */ user-select: none; } /* 菜单项样式 */ .context-menu-item { padding: 8px 16px; cursor: pointer; font-size: 14px; color: #333; /* hover 效果 */ transition: background-color 0.2s; } .context-menu-item:hover { background-color: #f5f5f5; } /* 菜单图标与文字间距 */ .context-menu-item i { width: 16px; text-align: center; } /* 分隔线样式 */ .context-menu-separator { height: 1px; margin: 4px 0; background-color: #e0e0e0; } /* 隐藏菜单的类(配合 Vue 状态控制) */ .hidden { display: none; } </style>
10-25
【无人机】基于改进粒子群算法的无人机路径规划研究[和遗传算法、粒子群算法进行比较](Matlab代码实现)内容概要:本文围绕基于改进粒子群算法的无人机路径规划展开研究,重点探讨了在复杂环境中利用改进粒子群算法(PSO)实现无人机三维路径规划的方法,并将其与遗传算法(GA)、标准粒子群算法等传统优化算法进行对比分析。研究内容涵盖路径规划的多目标优化、避障策略、航路点约束以及算法收敛性和寻优能力的评估,所有实验均通过Matlab代码实现,提供了完整的仿真验证流程。文章还提到了多种智能优化算法在无人机路径规划中的应用比较,突出了改进PSO在收敛速度和全局寻优方面的优势。; 适合人群:具备一定Matlab编程基础和优化算法知识的研究生、科研人员及从事无人机路径规划、智能优化算法研究的相关技术人员。; 使用场景及目标:①用于无人机在复杂地形或动态环境下的三维路径规划仿真研究;②比较不同智能优化算法(如PSO、GA、蚁群算法、RRT等)在路径规划中的性能差异;③为多目标优化问题提供算法选型和改进思路。; 阅读建议:建议读者结合文中提供的Matlab代码进行实践操作,重点关注算法的参数设置、适应度函数设计及路径约束处理方式,同时可参考文中提到的多种算法对比思路,拓展到其他智能优化算法的研究与改进中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值