CollectionView单元格滚动/点击后Alpha属性丢失问题求助
问题:CollectionView单元格置灰Alpha值滚动后丢失,交互状态保留
我用CollectionView展示设备状态,把无货设备的单元格Alpha设为0.2实现置灰效果,但滚动屏幕或点击单元格后,单元格重载时Alpha设置丢失,原本置灰的单元格恢复正常透明度,不过cell.userInteractionEnabled的设置能正常保留。
相关实现代码
CollectionView数据源方法
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = myCollectionView.dequeueReusableCell(withReuseIdentifier: "MyCollectionViewCell", for: indexPath) as! MyCollectionViewCell self.allDevices = self.allDevices.sorted(by: {$0.givenName.lowercased() < $1.givenName.lowercased()}) DispatchQueue.main.async { let deviceSKU = self.allDevices[indexPath.row].name let deviceName = self.allDevices[indexPath.row].givenName var alphaValue = 1.0 var enableValue = true if self.allDevices[indexPath.row].connectFlag != nil { alphaValue = (self.allDevices[indexPath.row].connectFlag == "1") ? 1.0 : 0.2 enableValue = (self.allDevices[indexPath.row].connectFlag == "1") ? true : false } if deviceSKU == "STS001" { let deviceImage = (self.allDevices[indexPath.row].state == true) ? UIImage(named: "socket-green.png") : UIImage(named: "socket-red.png") cell.configure(with: deviceImage!, name: deviceName, offline: alphaValue, enabled: enableValue) } if deviceSKU == "DWS01" { let deviceImage = (self.allDevices[indexPath.row].state == true) ? UIImage(named: "door-close2.png") : UIImage(named: "door-open2.png") cell.configure(with: deviceImage!, name: deviceName, offline: alphaValue, enabled: enableValue) } if deviceSKU == "BWS01" { let deviceImage = (self.allDevices[indexPath.row].state == true) ? UIImage(named: "wallsocket-on.png") : UIImage(named: "wallsocket-off.png") cell.configure(with: deviceImage!, name: deviceName, offline: alphaValue, enabled: enableValue) } if deviceSKU == "5CHN" { let deviceImage = UIImage(named: "5Channel.png") cell.configure(with: deviceImage!, name: deviceName, offline: alphaValue, enabled: enableValue) } } return cell }
UICollectionViewCell的configure函数
public func configure(with image: UIImage, name: String, offline : CGFloat, enabled : Bool){ deviceImage.image = image deviceName.text = name self.alpha = offline self.isUserInteractionEnabled = enabled }
解决方案
问题根源
cellForItemAt本身运行在主线程,你额外嵌套了DispatchQueue.main.async,导致单元格配置延迟。CollectionView的复用机制会在异步块执行前就将单元格返回并渲染,滚动或重载时,新复用的单元格可能还没等到Alpha设置就已经显示,导致置灰效果丢失。- 每次单元格复用都对
allDevices数组排序,会导致数据源顺序不稳定,干扰配置逻辑的准确性。
修复步骤
- 移除不必要的异步块:直接在
cellForItemAt中同步配置单元格。 - 提前排序数据源:在获取到设备数据后统一排序,不要每次复用单元格都执行排序。
- 优化SKU判断逻辑:用
switch替代多个if,提升代码可读性和维护性。
修改后的代码
调整后的数据源方法
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = myCollectionView.dequeueReusableCell(withReuseIdentifier: "MyCollectionViewCell", for: indexPath) as! MyCollectionViewCell // 直接取对应位置的设备数据 let device = allDevices[indexPath.row] let deviceSKU = device.name let deviceName = device.givenName var alphaValue: CGFloat = 1.0 var enableValue = true // 处理置灰和交互状态 if let connectFlag = device.connectFlag { alphaValue = connectFlag == "1" ? 1.0 : 0.2 enableValue = connectFlag == "1" } // 根据SKU获取对应图片 var deviceImage: UIImage! switch deviceSKU { case "STS001": deviceImage = device.state ? UIImage(named: "socket-green.png") : UIImage(named: "socket-red.png") case "DWS01": deviceImage = device.state ? UIImage(named: "door-close2.png") : UIImage(named: "door-open2.png") case "BWS01": deviceImage = device.state ? UIImage(named: "wallsocket-on.png") : UIImage(named: "wallsocket-off.png") case "5CHN": deviceImage = UIImage(named: "5Channel.png") default: deviceImage = UIImage() // 可设置默认占位图 } // 同步配置单元格 cell.configure(with: deviceImage, name: deviceName, offline: alphaValue, enabled: enableValue) return cell }
数据源排序的正确位置
在获取到设备数据后执行排序,再刷新CollectionView:
// 示例:获取设备数据完成后排序 allDevices = allDevices.sorted(by: {$0.givenName.lowercased() < $1.givenName.lowercased()}) myCollectionView.reloadData()
内容的提问来源于stack exchange,提问作者AbheshekSharma
相关产品推荐
相关产品推荐

