【问题标题】:Dynamic Cell Height Issue动态单元高度问题
【发布时间】:2017-08-20 04:20:37
【问题描述】:

我有一个动态单元格,两个图像之间有一个标签,每个单元格底部图像下方有两个按钮。标签的大小取决于标签中的行数,可以是任何值。我在cellForRowAt indexPath 中获得了标签的文本。在我的viewDidLoad() 中,我已经通过使用这个设置了一个动态单元格:

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 265

问题:标签超过1行时,单元格的高度大小不变。它只有在两种情况下才有机会获得正确的大小:1)当我刷新表格时。 2)当我向下滚动损坏的单元格不在视图中时,然后当我向上滚动时,损坏的单元格位于正确的位置。

我尝试过的:经过数小时的尝试后,有许多消息来源说 2 个相同的事情:1) 确保所有项目对其所有项目都有限制双方(我这样做了,同样的问题发生了)。 2)唯一的另一个说使用UITableViewAutomaticDimensionestimatedRowHeight(我有)。

我该如何解决这个问题或者我错过了什么?

编辑:在得到它是哪种类型的单元格后,我在cellForRowAt indexPath 中调用标签的文本(我有 3 个,它们都做不同的事情)。代码如下:

    func loadNews() {        
            //start finding followers
            let followQuery = PFQuery(className: "Follow")
            followQuery.whereKey("follower", equalTo: PFUser.current()?.objectId! ?? String())
            followQuery.findObjectsInBackground { (objects, error) in
                if error == nil {

                    self.followArray.removeAll(keepingCapacity: false)

                    //find users we are following
                    for object in objects!{
                        self.followArray.append(object.object(forKey: "following") as! String)
                    }
                    self.followArray.append(PFUser.current()?.objectId! ?? String()) //so we can see our own post


                    //getting related news post
                    let newsQuery = PFQuery(className: "News")
                    newsQuery.whereKey("user", containedIn: self.followArray) //find this info from who we're following
                    newsQuery.limit = 30
                    newsQuery.addDescendingOrder("createdAt")
                    newsQuery.findObjectsInBackground(block: { (objects, error) in
                        if error == nil {     
                            //clean up
                            self.newsTypeArray.removeAll(keepingCapacity: false)
                            self.animalArray.removeAll(keepingCapacity: false)
                            self.newsDateArray.removeAll(keepingCapacity: false)

                            for object in objects! {                            
                                self.newsTypeArray.append(object.value(forKey: "type") as! String) //get what type (animal / human / elements)

                                self.animalArray.append(object.value(forKey: "id") as! String) //get the object ID that corresponds to different class with its info
                                self.newsDateArray.append(object.createdAt) //get when posted
                            }
                            self.tableView.reloadData()
                        } else {
                            print(error?.localizedDescription ?? String())
                        }
                    })
                } else {
                    print(error?.localizedDescription ?? String())
                }
            }   
        }



        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let type = newsTypeArray[indexPath.row]

    if type == "element" {
      //fills cell just like animal one
    } else if type == "human" {
      //fills cell just like animal one

    } else { //its an animal cell

                            let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! AnimalCell
                            let query = query(className: "Animals")
                            query.whereKey("objectId", equalTo: animalArray[indexPath.row])
                            query.limit = 1
                            query.findObjectsInBackground(block: { (objects, error) in
                                if error == nil {                            
                                    for object in objects! {

                                        let caption = (object.object(forKey: "caption") as! String)
                                        cell.captionLabel.text = caption

                                    }                               
                                } else {
                                    print(error?.localizedDescription ?? String())
                                }
                            })
           return cell
        }
    }

【问题讨论】:

  • 你把标签 numberOfLines 改成 0 了吗?
  • 标签行数为0 @Imad Ali
  • 显示您的自定义单元格
  • 请参考here,如果还有疑问可以询问。
  • @fphelp 你能添加你的 cellForRowAt 方法吗?特别是如果您正在执行任何类型的调度或网络调用来获取标签文本?

标签: ios swift xcode uitableview swift3


【解决方案1】:

1.检查您是否在单元格中使用了正确的constraints

2。实现这些UITableViewDelegate 方法:

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
    return UITableViewAutomaticDimension
}

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat
{
    return 265
}

删除这两行:

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 265

截图:

1.查看层次结构:Image1 -> Label -> Image2 -> Button1 -> Button2

2。输出

如果它不起作用:

在您的自定义UITableViewCell 中提供preferredMaxLayoutWidthUILabel,即

override func awakeFromNib()
{
    super.awakeFromNib()
    self.label.preferredMaxLayoutWidth = UIScreen.main.bounds.width //Provide here the calculated width of your label
}

UITableViewDataSource方法:

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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableCell
    if indexPath.row == 0
    {
        cell.label.text = "When the label is more than 1 line, the size of the height of the cell does not change."
    }
    else
    {
        cell.label.text = "When the label is more than 1 line, the size of the height of the cell does not change. It only chances to the correct size in two instances: 1) When I refresh the table. 2) when I scroll down where the broken cell is not in the view then when I scroll back up the broken cell is at the correct position."
    }
    return cell
}

【讨论】:

  • 遗憾的是得到了同样的结果
  • 我在cellForRowAt indexPath 中获得单元格标签的文本这一事实是否与问题有关?
  • 不,完全没问题。我也会添加 UITableViewDataSource 的代码,以便您有更好的想法。
  • 您使用的是哪个 iOS 版本?
  • 我在 Xcode 模拟器上运行 iOS 10.3,在 iPhone 6s 上运行 iOS 10.3。并且在两种设备上都收到相同的结果
【解决方案2】:

这听起来像是在加载初始表数据后设置标签的内容(可能使用后台方法从网络获取值?)。

如果是这种情况,您可以使用UITableView.reloadRows(at:with:) 方法重新加载表格中的那个单元格。见:https://developer.apple.com/documentation/uikit/uitableview/1614935-reloadrows

例如:tableView.reloadRows(at: [indexPathToCell], with: .automatic)

【讨论】:

  • 在标签的文本被收集之后,我在cellForRowAt 中实现了tableView.reloadRows,并且由于某种原因它开始重新加载我的所有行。我正在使用解析,我只是查询标签的文本并设置label.text = \\what I get from server没什么特别的
  • 那是你的问题。 Parse 正在执行网络调用,您在 cellForRowAt 方法返回后的某个时间点设置标签的值。所以你需要在那之后触发重新加载。在label.text = ... 行之后添加DispatchQueue.main.async { tableView.reloadRows(at: [indexPathToCell], with: .none) }
  • @fphelp 注意:根据标签文本更改的频率,您可能最好在视图出现之前的某个时间通过解析加载值,并将其缓存。不需要每次单元格出现在屏幕上时都使用 Parse,除非数据可以经常更改。
  • 我尝试了DispatchQueue.main.async { tableView.reloadRows(at: [indexPathToCell], with: .none) },它一遍又一遍地重新加载单元格。我用let index = IndexPath(row: indexPath.row, section: 0) 替换了你的“indexPathToCell”
  • 我想再次加载文本标签,但这很复杂,因为我有 2 个其他单元格可以进入 tableview 执行与我遇到问题的单元格不同的事情。因此,我将来自不同类的类型及其对应的 objectId 加载到数组中,然后在每个单元格中加载它们的内容。 如果有可能的解决方案,我该如何解决?
猜你喜欢
  • 1970-01-01
  • 2015-08-10
  • 1970-01-01
  • 2017-07-19
  • 1970-01-01
  • 1970-01-01
  • 2014-12-15
  • 2013-03-13
相关资源
最近更新 更多