iOS Developer

【iOS】关于tableview单选cell的一点尝试和见解

2017-03-21  本文已影响1000人  清無

2017.09.19更新

不错的单选效果

原理分析

let selectedRow = IndexPath(row: 0, section: 0)
tableView.selectRow(at: selectedRow, animated: false, scrollPosition: .none)

这种方式来设置最初的默认选中行;

代码实现

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)
    
    accessoryType = selected ? .checkmark : .none
}
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

// 由于我这个例子中的数据都是dead,所以tableView很快创建好,你可以在网络数据请求的回调中这样操作
    tableView.reloadData()
    tableView.beginUpdates()
    tableView.selectRow(at: IndexPath(row: 0, section: 0), animated: false, scrollPosition: .top)
    tableView.endUpdates()
}

旧方法

先看一个demo:

单选

Note: 功能上看起来是没什么问题,可以实现正常的单选选中,但大家有没有发现一个细节性的bug:选中后面的cell时候,tableview会跳一下,然后到自动滚到顶部了

原因

typealias Item = (title: String, selected: Bool)
private var data = [Item]()

// 选中
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
     tableView.deselectRow(at: indexPath, animated: true)
     
// 改变数据源控制属性值
     data[indexPath.row].selected = true
// 刷新表格
    tableView.reloadData()
 }

// 复用
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        
// 当前选中的cell样式
        cell.accessoryType = data[indexPath.row].selected ? .checkmark : .none
        
        return cell
}

改进

尝试一:

属性设置

// 默认选中第一行
private var selectedIndex = IndexPath(row: 0, section: 0)

// 选中cell样式设置
private func setAccessoryTypeOfCellAt(index: IndexPath, selected: Bool){
        let cell = tableView.cellForRow(at: index)
        cell?.accessoryType = selected ? .checkmark : .none
}

选中

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
// 取消选中上一个cell
        setAccessoryTypeOfCellAt(index: selectedIndex, selected: false)
// 选中当前cell
        setAccessoryTypeOfCellAt(index: indexPath, selected: true)
// 记录indexPath,便于cell复用时能正确显示其样式
        selectedIndex = indexPath
}

复用

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        
        cell.textLabel?.text = data[indexPath.row]
        cell.accessoryType = indexPath == selectedIndex ? .checkmark : .none

        return cell
}

改进效果

不会跳动

见解

上一篇下一篇

猜你喜欢

热点阅读