简体   繁体   English

选择单元格时奇怪的 tableview 行为

[英]weird tableview behavior when cell is selected

My tableview has a weird behavior when a cell is selected but this behavior is not seen always. My tableview has a weird behavior when a cell is selected but this behavior is not seen always. When a cell has been selected some cells which are below the selected cell moves.当一个单元格被选中时,选定单元格下方的一些单元格会移动。 These two gifs will show you the behavior in the two cases when it is shown and when it doesn't appear.这两个 gif 将向您显示显示和不显示两种情况下的行为。 this is the tableview without weird behavior and this is the tableview with the weird behavior and this is my code :这是没有奇怪行为的表视图,这是具有奇怪行为的表视图,这是我的代码:

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell : UserTableViewCell = (tableView.dequeueReusableCell(withIdentifier: "userCell") as? UserTableViewCell)!
    if(self.firebaseUsers.count != 0){
    cell.influentBackgroudView.layer.cornerRadius=10
        let url = URL.init(string:  String().loadCorrectUrl(url:firebaseUsers[indexPath.row].image))
        cell.influentImageView.contentMode = .scaleAspectFit
        cell.influentImageView!.sd_setImage(with: url!, placeholderImage: UIImage.init(named: "placeholder"),options: [.continueInBackground,.progressiveDownload], completed: { (image, error, cacheType, imageURL) in
            if (error != nil) {
                cell.influentImageView!.image = UIImage(named: "placeholder")
            } else {
                cell.influentImageView.contentMode = .scaleAspectFill
                cell.influentImageView.image = image
            }

        })
        cell.influentImageView.layer.cornerRadius=10
        cell.influentImageView.layer.masksToBounds = true
        cell.influentNameLabel.text=" " + firebaseUsers[indexPath.row].name + " "
        cell.influentNameLabel.adjustsFontSizeToFitWidth = true
        cell.influentNameLabel.textAlignment = .center
        if(selectedCellIndex==indexPath ){
        cell.influentBackgroudView.isHidden=false
            }
        else{
            cell.influentBackgroudView.isHidden=true
            }
    cell.selectionStyle = .none
    }

    return cell 
} 
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let previousIndex=selectedCellIndex
        selectedCellIndex=indexPath
        if(previousIndex==selectedCellIndex){
            let nextVC = storyboard?.instantiateViewController(withIdentifier: "VisitedProfileViewController") as! VisitedProfileViewController
            nextVC.passedUser = firebaseUsers[selectedCellIndex!.row]
            navigationController?.pushViewController(nextVC, animated: true)
        }
        if(previousIndex==nil){
            tableView.reloadRows(at: [indexPath], with:.none)
        }
        else{
            if(previousIndex != indexPath){
                tableView.reloadRows(at: [indexPath,previousIndex!], with: .none)
            }
            else {
                tableView.reloadRows(at: [indexPath], with: .none)

                }
        }
}

thank you guys for your help!谢谢你们的帮助!

As identified from the comments the issue you are facing is produced by calling reloadRows when you press a cell with conjunction of incorrect estimated row heights.从评论中可以reloadRows当您按下带有错误估计行高的单元格时,您面临的问题是通过调用reloadRows产生的。 So either reloading needs to be removed or estimated height corrected.因此,要么需要移除重新加载,要么需要修正估计高度。 The first solution is already covered in an answer provided by A. Amini. A. Amini 提供的答案中已经涵盖了第一个解决方案。

Since many of such anomalies are related to estimated row height it still makes sense to improve it.由于许多此类异常与估计的行高有关,因此改进它仍然有意义。

For simple static row heights you can either implement a delegate method for instance对于简单的静态行高,您可以实现一个委托方法,例如

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return indexPath.row == 0 ? 44.0 : 200.0
}

where the values are exactly the same as in your heightForRowAt method.其中值与heightForRowAt方法中的值完全相同。 Or if all rows have same hight you can remove this delegate method but set the heights directly in some initialization method like:或者,如果所有行都具有相同的高度,您可以删除此委托方法,但直接在某些初始化方法中设置高度,例如:

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.rowHeight = 200
    tableView.estimatedRowHeight = tableView.rowHeight
}

When more complicated cells are introduced and automatic cell height is used we usually use a height cache of cells.当引入更复杂的单元格并使用自动单元格高度时,我们通常使用单元格的高度缓存。 It means we need to save height of a cell when it disappears so we may use it later.这意味着我们需要在单元格消失时保存它的高度,以便我们稍后使用它。 All heights are saved in a dictionary of type [IndexPath: CGFloat] .所有高度都保存在[IndexPath: CGFloat]类型的字典中。 A very simple implementation should look like this:一个非常简单的实现应该是这样的:

private var cellHeightCache: [IndexPath: CGFloat] = [IndexPath: CGFloat]()

func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    cellHeightCache[indexPath] = cell.bounds.height
}

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return cellHeightCache[indexPath] ?? UITableView.automaticDimension
}

In some cases extra work is needed like clearing the cache when table view is reloaded.在某些情况下,需要额外的工作,例如在重新加载表视图时清除缓存。

The reason why this is happening is because table view will not reload cells around the cells you currently see but rather check the content offset and compute which cells you were supposed to be seeing.发生这种情况的原因是因为表格视图不会在您当前看到的单元格周围重新加载单元格,而是检查内容偏移量并计算您应该看到哪些单元格。 So any call to reload may make the table view jump or animate cells due to wrong estimated row height.因此,由于错误的估计行高,任何重新加载调用都可能使表格视图跳转或动画单元格。

The main problem was you're reloading tableView after "each" selection.主要问题是您在“每个”选择后重新加载 tableView。 Try this code out and let me know if you need more help.试试这个代码,如果您需要更多帮助,请告诉我。

class MyTableViewClass: UITableViewController {
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "userCell" as! UserTableViewCell

        if !self.firebaseUsers.isEmpty {

            cell.influentBackgroudView.layer.cornerRadius = 10
            cell.influentImageView.contentMode = .scaleAspectFit

            let url = URL(string: firebaseUsers[indexPath.row].image)

            cell.influentImageView!.sd_setImage(with: url!, placeholderImage: UIImage(named: "placeholder"),options: [.continueInBackground,.progressiveDownload], completed: { (image, error, cacheType, imageURL) in
                if error != nil {
                    cell.influentImageView.contentMode = .scaleAspectFill
                }
            })

            cell.influentImageView.layer.cornerRadius=10
            cell.influentImageView.layer.masksToBounds = true
            cell.influentNameLabel.text = " \(firebaseUsers[indexPath.row].name) "
            cell.influentNameLabel.adjustsFontSizeToFitWidth = true
            cell.influentNameLabel.textAlignment = .center

            cell.selectionStyle = .none
        }

        return cell
    }


    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let nextVC = storyboard?.instantiateViewController(withIdentifier: "VisitedProfileViewController") as! VisitedProfileViewController
        nextVC.passedUser = firebaseUsers[indexPath.row]
        navigationController?.pushViewController(nextVC, animated: true)
    }
}


class UserTableViewCell: UITableViewCell {

    override var isSelected: Bool {
        didSet {
            if isSelected {
                // Selected behavior, like change Background to blue
            } else {
                // Deselected behavior, change Background to clear
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM