UITableview 部分 - 如何正确重新计算高度?
Posted
技术标签:
【中文标题】UITableview 部分 - 如何正确重新计算高度?【英文标题】:UITableview Section - How to recalculate the height properly? 【发布时间】:2019-01-16 10:51:14 【问题描述】:视频:
https://youtu.be/sSHrxSIHUM4
您可以在视频中看到我遇到的问题。图像高度约束被破坏,导致标签也缺少高度。它们位于 tableview 部分(UITableHeaderFooter
类)。我用automaticDimension
计算了它的高度并修正了结果。
这是图像视图约束。 (默认高度约束为 184 并且在运行时更新取决于比率。)
https://uphinhnhanh.com/image/SAezyz
以及标签约束:
https://uphinhnhanh.com/image/SAeT5Y
问题发生在我致电table reload
重新配置剖面视图数据和高度然后下载图像之后。我收到了损坏的约束警告。 Xcode 打破了导致问题的 imageview 高度约束。
(
"<NSLayoutConstraint:0x2807252c0 UIImageView:0x109c002d0.height == 735.885 (active)>",
"<NSLayoutConstraint:0x280727160 UIImageView:0x109c007f0.height == 40 (active)>",
"<NSLayoutConstraint:0x280715900 UIView:0x109c00d10.height == 51 (active)>",
"<NSLayoutConstraint:0x2807140f0 UILayoutGuide:0x281d7e680'UIViewSafeAreaLayoutGuide'.bottom == UIView:0x109c00d10.bottom (active)>",
"<NSLayoutConstraint:0x2807174d0 V:|-(11)-[UIImageView:0x109c007f0] (active, names: '|':engie_up.PostDetailHeaderView:0x109c00000 )>",
"<NSLayoutConstraint:0x280717c50 V:[UIImageView:0x109c007f0]-(18.5)-[engie_up.KwExpandableContextLabel:0x10491c600'bfbfnff'] (active)>",
"<NSLayoutConstraint:0x280715130 V:[engie_up.KwExpandableContextLabel:0x10491c600'bfbfnff']-(18)-[UIImageView:0x109c002d0] (active)>",
"<NSLayoutConstraint:0x280714fa0 V:[UIImageView:0x109c002d0]-(0)-[UIView:0x109c00d10] (active)>",
"<NSLayoutConstraint:0x28072ad00 'UIView-Encapsulated-Layout-Height' engie_up.PostDetailHeaderView:0x109c00000.height == 343 (active)>",
"<NSLayoutConstraint:0x2807179d0 'UIViewSafeAreaLayoutGuide-bottom' V:[UILayoutGuide:0x281d7e680'UIViewSafeAreaLayoutGuide']-(0)-| (active, names: '|':engie_up.PostDetailHeaderView:0x109c00000 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x2807252c0 UIImageView:0x109c002d0.height == 735.885 (active)>
我注意到'UIView-Encapsulated-Layout-Height'
是估计高度。
获取代码很简单,因为我使用的是翠鸟
let ratio = CGFloat(image.width) / CGFloat(image.height)
userContentImageViewHeightConstraint.constant = CGFloat((UIScreen.main.bounds.width) / ratio)
self.userContentImageView.kf.indicatorType = .activity
self.userContentImageView.kf.setImage(with: URL(string: image.url), completionHandler: (_, _, _, _) in
self.setNeedsLayout()
self.layoutIfNeeded()
)
所以我想问一下如何正确修复约束中断?
谢谢。
【问题讨论】:
您的视图的视觉外观是什么?您可以添加您制作的内容和您想要制作的内容的屏幕截图吗? @SyedQamarAbbas,我已经上传了视频。当我向下滚动并且图像被收缩和拉伸时,您可以看到标签丢失。 【参考方案1】:更新:我删除了图像高度约束并添加了纵横比约束,现在中断消失了,但在视频中得到了相同的结果
let ratio = CGFloat(image.width) / CGFloat(image.height)
let constraint = NSLayoutConstraint(item: self.userContentImageView,
attribute: NSLayoutConstraint.Attribute.width,
relatedBy: NSLayoutConstraint.Relation.equal,
toItem: self.userContentImageView,
attribute: NSLayoutConstraint.Attribute.height,
multiplier: ratio,
constant: 0.0)
constraint.priority = 999
self.userContentImageViewAspectConstraint = constraint
更新 2:2019 年 1 月 18 日
最后,我找到了问题的根本原因。 我没有注意到底部视图的底部约束与安全区域布局对齐。这导致在开始时,视图有点被拉到标签栏上方,并且产生了额外的空间并破坏了图像约束的高度(其优先级为 999)。我将其更改为与超级视图对齐,然后问题消失了。
【讨论】:
【参考方案2】:我再次检查了您随附的屏幕截图。一切对我来说都很好。现在我仍然在这里猜测。通常,当发生此类约束警告时,即使需要我的时间,我也会解决它。很高兴您已经有了数据图像大小。
从此代码块:
self.userContentImageView.kf.setImage(with: URL(string: image.url), completionHandler: (_, _, _, _) in
self.setNeedsLayout()
self.layoutIfNeeded()
)
这很难看,肯定会产生闪烁或不需要的动画/移动错误,就像在您的视频演示中一样。
通常,对我来说,self.layoutIfNeeded()
足以在调整任何视图的约束之后调整布局。
所以你的代码块可以转换成这样:
let ratio = CGFloat(image.width) / CGFloat(image.height)
userContentImageViewHeightConstraint.constant = CGFloat((UIScreen.main.bounds.width) / ratio)
self.layoutIfNeeded()
self.userContentImageView.kf.indicatorType = .activity
self.userContentImageView.kf.setImage(with: URL(string: image.url), completionHandler: (_, _, _, _) in )
或者更好,(我意识到这是在你的牢房里):
在您返回cellForRow
中的单元格之前,您需要调整约束!我之前有一个个人项目,其流程/逻辑与您的相同 - 带有网络调用的随机图像大小。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
self.feedCell = tableView.dequeueReusableCell(withIdentifier: self.feedCell.identifier)
as! FeedTableViewCell
self.feedCell.indexPath = indexPath
self.feedCell.delegate = self
let post = self.catPosts[indexPath.row]
self.feedCell.post = post
let aspectRatio = self.feedCell.getAspectRatioAccordingToiPhones(cellImageFrame: self.feedCell.frame.size, media: post.media!.first!)
self.feedCell.constraint_PostHeight?.update(offset: aspectRatio)
return self.feedCell
在我的牢房里,我有我的getAspectRadio....
方法:
func getAspectRatioAccordingToiPhones(cellImageFrame: CGSize, media: Media) -> CGFloat
guard let widthNumber = NumberFormatter().number(from: catMedia.width!),
let heightNumber = NumberFormatter().number(from: catMedia.height!) else
return UIScreen.main.bounds.width
let imageWidth = CGFloat(truncating: widthNumber)
let imageHeight = CGFloat(truncating: heightNumber)
let widthOffset = imageWidth - cellImageFrame.width
let widthOffsetPercentage = (widthOffset * 100) / imageWidth
let heightOffset = (widthOffsetPercentage * imageHeight) / 100
let effectiveHeight = imageHeight - heightOffset
return effectiveHeight
我希望这对你现在有所帮助:) 祝你好运!
【讨论】:
继续前进,不要在意那些嚣张的人。他们是人们不想在***上提出问题的原因。问题对他们来说可能很容易,但对其他人来说并不容易。顺便说一句,在做出任何回答之前,请仔细阅读我的问题。感谢阅读。 对。谢谢!我编辑了我的整个答案。看看这个。 @QuangLuu以上是关于UITableview 部分 - 如何正确重新计算高度?的主要内容,如果未能解决你的问题,请参考以下文章
iOS为啥只有在重新加载UITableView后才能正确显示UIView
UITableView 两次重新加载数据,但没有正确显示数据