动态单元高度问题
Posted
技术标签:
【中文标题】动态单元高度问题【英文标题】: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)唯一的另一个说使用UITableViewAutomaticDimension
和estimatedRowHeight
(我有)。
我该如何解决这个问题或者我错过了什么?
编辑:在得到它是哪种类型的单元格后,我在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 方法吗?特别是如果您正在执行任何类型的调度或网络调用来获取标签文本? 【参考方案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
中提供preferredMaxLayoutWidth
的UILabel
,即
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 加载到数组中,然后在每个单元格中加载它们的内容。 如果有可能的解决方案,我该如何解决?以上是关于动态单元高度问题的主要内容,如果未能解决你的问题,请参考以下文章