UITextView在UITableViewCell中的奇怪行为 [英] Strange behavior of UITextView in UITableViewCell

查看:120
本文介绍了UITextView在UITableViewCell中的奇怪行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含几个堆栈视图的单元格,底部stackView包含一个textView和一个自定义分隔符。





我想创建一个选项,当用户点击单元格时,它会显示点击文本视图的全文,因此该单元格中的最大行数为0,而其他单元格中的最大行数应为0是



我用过这个教程

解决方案

在选择时动态调整UITableViewCell



使用个人选择索引是危险的事情。您不仅可能会错过 didSelectRowAtIndexPath 中的角落情况条件,它还不能用于多个选择。

您应该拆分单元格扩展/压缩通知进入2个不同的块(无需跟踪 selectedIndexPath ,更强大的代码)



展开

 覆盖func tableView(_ tableView:UITableView ,
didSelectRowAt indexPath:IndexPath){
self.reloadRowsAtIndexPaths(tableView,
indexPath:indexPath)
}

合约

 覆盖func tableView(_ tableView:UITableView,
didDeselectRowAt indexPath:IndexPath){
self.reloadRowsAtIndexPaths(tableView,
indexP) ath:indexPath)
}






选择被selectRowAtIndexPath销毁



这可以防止 didDeselectRowAtIndexPath 被调用的。
解决方法是缓存整个选择,而不是单个索引,并在重新加载后恢复此类选择。



完整代码



注意维护 cacheSelectedRows 的时间和方式。这使用普通的 UITableViewCell 。它只需要一个 reuseIdentifier

  class TableViewController:UITableViewController {
var cacheSelectedRows:[IndexPath]? = nil

覆盖func viewDidLoad(){
super.viewDidLoad()
tableView.estimatedRowHeight = 160
tableView.rowHeight = UITableViewAutomaticDimension
}

覆盖func tableView(_ tableView:UITableView,numberOfRowsInSection section:Int) - > Int {
return 8
}

override func tableView(_ tableView:UITableView,cellForRowAt indexPath:IndexPath) - > UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier:reuseIdentifier,for:indexPath)

if let textLabel = cell.textLabel {
textLabel.backgroundColor = UIColor.clear

textLabel.numberOfLines = 1
if let cacheSelectedRows = cacheSelectedRows {
textLabel.numberOfLines =(cacheSelectedRows.contains(indexPath))? 0:1
}
textLabel.text =\(1 + indexPath.row),Lorem ipsum dolor sit amet,consectetur adipiscing elit,sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.Duis aute irure dolor in repreptderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur。Excepteur sint occaecat cupidatat non proident,sunt in culpa qui officia deserunt mollit anim id est laborum。
}
返回单元格
}

覆盖func tableView(_ tableView:UITableView,didSelectRowAt indexPath:IndexPath){
self.reloadRowsAtIndexPaths(tableView,indexPath) :indexPath)
}

覆盖func tableView(_ tableView:UITableView,didDeselectRowAt indexPath:IndexPath){
self.reloadRowsAtIndexPaths(tableView,indexPath:indexPath)
}

func reloadRowsAtIndexPaths(_ tableView:UITableView,indexPath:IndexPath){
cacheSelectedRows = tableView.indexPathsForSelectedRows

tableView.reloadRows(at:[indexPath],with: .fade)

//恢复选择
如果让cacheSelectedRows = cacheSelectedRows {
表示cacheSelectedRows中的路径{
self.tableView.selectRow(at:path,animated: false,scrollPosition:.none)
}
}
}
}

演示



< img src =https://i.stack.imgur.com/GHHUm.gifalt =动画演示>






►在 GitHub 上查找此解决方案以及 Swift Recipes


I have a cell that contains a few stackviews, bottom stackView contains a textView and a custom separator.

I want to create an option, when user tap on cell, it shows whole text of tapped text view, so number of maximum lines in that cell is 0 and in other cells should be 3.

I used this tutorial http://www.roostersoftstudios.com/2011/04/14/iphone-uitableview-with-animated-expanding-cells/ and I modified it a little, my code:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier(iden_tableViewCell4) as! TableViewCell4


    if let selectedCellIP = selectedIndexPath {
        if indexPath == selectedCellIP {
            cell.textTextVIew.textContainer.maximumNumberOfLines = 0
        }
        else {
            cell.textTextVIew.textContainer.maximumNumberOfLines = textVIewMaxNumberOfLines
        }

    }
    else {
        cell.textTextVIew.textContainer.maximumNumberOfLines = textVIewMaxNumberOfLines
    }

    return cell
}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.deselectRowAtIndexPath(indexPath, animated: true)

    //The user is selecting the cell which is currently expanded
    //we want to minimize it back
    if selectedIndexPath == indexPath {
        selectedIndexPath = nil
        tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)

        return
    }

    //First we check if a cell is already expanded.
    //If it is we want to minimize make sure it is reloaded to minimize it back
    if let selIndexPath = selectedIndexPath {

        let previousPath = selIndexPath
        selectedIndexPath = indexPath
        tableView.reloadRowsAtIndexPaths([previousPath], withRowAnimation: .Fade)

    }


    //Finally set the selected index to the new selection and reload it to expand
    selectedIndexPath = indexPath
    tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)

}

in my viewDidLoad I set tableView.estimatedRowHeight = 160 tableView.rowHeight = UITableViewAutomaticDimension

Expansion and contraction work well, but textView height of other cells has a strange behavior. When first cell is extended, an I scroll down, the last is extended too, and should not be.

解决方案

Dynamically Resize UITableViewCell upon Selection

Playing with individual selection indexes is dangerous business. Not only are you likely to miss corner case conditions in didSelectRowAtIndexPath, it cannot possibly work for multiple selections.
You should split the cell expansion/compression notification into 2 distinct blocks (no need to keep track of selectedIndexPath, more robust code):

Expand

override func tableView(_ tableView: UITableView,
                        didSelectRowAt indexPath: IndexPath) {
    self.reloadRowsAtIndexPaths(tableView,
                                indexPath:indexPath)
}

Contract

override func tableView(_ tableView: UITableView,
                        didDeselectRowAt indexPath: IndexPath) {
    self.reloadRowsAtIndexPaths(tableView,
                                indexPath:indexPath)
}


Selection is destroyed by selectRowAtIndexPath

This prevents didDeselectRowAtIndexPath from ever being invoked. A workaround is to cache the entire selection, not individual indexes, and to restore such selection after reload.

Complete code:

Notice when and how cacheSelectedRows is maintained. This uses a plain UITableViewCell. All it needs is a reuseIdentifier.

class TableViewController: UITableViewController {
    var cacheSelectedRows:[IndexPath]? = nil

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.estimatedRowHeight = 160
        tableView.rowHeight = UITableViewAutomaticDimension
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 8
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)

        if let textLabel = cell.textLabel {
            textLabel.backgroundColor = UIColor.clear

            textLabel.numberOfLines = 1
            if let cacheSelectedRows = cacheSelectedRows {
                textLabel.numberOfLines = (cacheSelectedRows.contains(indexPath)) ? 0 : 1
            }
            textLabel.text = "\(1 + indexPath.row), Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
        }
        return cell
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        self.reloadRowsAtIndexPaths(tableView, indexPath:indexPath)
    }

    override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
         self.reloadRowsAtIndexPaths(tableView, indexPath:indexPath)
    }

    func reloadRowsAtIndexPaths(_ tableView: UITableView, indexPath: IndexPath) {
        cacheSelectedRows = tableView.indexPathsForSelectedRows

        tableView.reloadRows(at: [indexPath], with: .fade)

        // Restore selection
        if let cacheSelectedRows = cacheSelectedRows {
            for path in cacheSelectedRows {
                self.tableView.selectRow(at: path, animated: false, scrollPosition: .none)
            }
        }
    }
}

Demo


► Find this solution on GitHub and additional details on Swift Recipes.

这篇关于UITextView在UITableViewCell中的奇怪行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆