[英]iOS: Collection view custom tag layout dynamic Height Swift
I am trying to create tag list view.我正在尝试创建标签列表视图。 Unfortunately I don't know How to work with Custom flow layout.不幸的是,我不知道如何使用自定义流程布局。 But I found to create pretty tag list.但我发现创建了漂亮的标签列表。 But encountered a problem with multi-line label.但是遇到了多行标签的问题。 If we used the text more than the collection view width, then the attribute.frame.height
should be multiplied like 40*numberOfLines
.如果我们使用的文本超过集合视图的宽度,那么attribute.frame.height
应该像40*numberOfLines
一样相乘。 Please help to solve this problem.请帮助解决这个问题。
Custom Flow Layout:自定义流程布局:
import UIKit
class CollectionViewRow {
var attributes = [UICollectionViewLayoutAttributes]()
var spacing: CGFloat = 0
init(spacing: CGFloat) {
self.spacing = spacing
}
func add(attribute: UICollectionViewLayoutAttributes) {
attributes.append(attribute)
}
var rowWidth: CGFloat {
return attributes.reduce(0, { result, attribute -> CGFloat in
return result + attribute.frame.width
}) + CGFloat(attributes.count - 1) * spacing
}
func layout(collectionViewWidth: CGFloat) {
var offset = spacing
for attribute in attributes {
attribute.frame.origin.x = offset
offset += attribute.frame.width + spacing
}
}
}
class UICollectionViewCenterLayout: UICollectionViewFlowLayout {
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let attributes = super.layoutAttributesForElements(in: rect) else {
return nil
}
var rows = [CollectionViewRow]()
var currentRowY: CGFloat = -1
for attribute in attributes {
if currentRowY != attribute.frame.midY {
currentRowY = attribute.frame.midY
rows.append(CollectionViewRow(spacing: 10))
}
rows.last?.add(attribute: attribute)
}
rows.forEach { $0.layout(collectionViewWidth: collectionView?.frame.width ?? 0) }
return rows.flatMap { $0.attributes }
}
}
Usage:用法:
let layout = UICollectionViewCenterLayout()
layout.estimatedItemSize = CGSize(width: 140, height: 40)
collectionView.collectionViewLayout = layout
collectionView.reloadData()
I tried to change height but It not working expected:我试图改变高度,但它无法正常工作:
func layout(collectionViewWidth: CGFloat) {
var offset = spacing
for attribute in attributes {
attribute.frame.origin.x = offset
let attributeTotalWidth = attribute.frame.width + spacing
if attributeTotalWidth > collectionViewWidth{
let multiplier: CGFloat = attributeTotalWidth/collectionViewWidth
let intVal = CGFloat(Int(multiplier))
let fullNumber = multiplier-intVal > 0 ? intVal+1 :
attribute.frame.size.height = fullNumber * 40
}
offset += attributeTotalWidth
}
}
Can you please help me to find out the solution to make variable item height based on the label text content?您能帮我找出根据标签文本内容制作可变项目高度的解决方案吗? Thanking you in advance!提前谢谢你!
@iDeveloper I tried to fix your code. @iDeveloper 我试图修复你的代码。
Here are the things you can do.以下是您可以做的事情。
Simplify your array.简化您的阵列。
let titles = ["Apple","Google","Computer", "Terminal", "Gross", "Form lands", "Water lands", "river", "mounts", "trees", "places", "parks", "towns", "cities","Lorem Ipsum is simply dummy text of the printing and typesettingindustry.","Hello","A","B","CAD","John","Nick","Lucas","Amy","Lawrance","Apple","Google","Computer", "Browser","Overflow","Hi","Hello","A","B","CAD","John","Nick","Lucas","Amy","Lawrance", "Lorem Ipsum is simply dummy text of the printing and typesetting industry.",""] let title = ["Apple","Google","Computer", "Terminal", "Gross", "Form lands", "Water lands", "river", "mounts", "trees", "places", "parks", "towns", "cities","Lorem Ipsum 只是印刷和排版行业的虚拟文本。","Hello","A","B","CAD","John","Nick" ,"卢卡斯","艾米","劳伦斯","苹果","谷歌","计算机","浏览器","溢出","嗨","你好","A","B"," CAD","John","Nick","Lucas","Amy","Lawrance", "Lorem Ipsum 只是印刷和排版行业的虚拟文本。",""]
You have to add a width constraint to your title label like this.您必须像这样向标题标签添加宽度约束。
End result最终结果
One could make the below code prettier by moving more code into Row, but it fixes the issue of clipped labels (as seen in the result image of the other answer).可以通过将更多代码移动到 Row 中来使下面的代码更漂亮,但它解决了剪辑标签的问题(如另一个答案的结果图像所示)。 The code is also a lot simpler and still works with labels that contain multiple lines (label.numberOfLines = 0)代码也简单了很多,并且仍然适用于包含多行的标签(label.numberOfLines = 0)
class CustomCollectionViewLayout: UICollectionViewFlowLayout {
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let attributes = super.layoutAttributesForElements(in: rect) else {
return nil
}
let collectionViewWidth = collectionView?.frame.width ?? 0
var rows = [Row]()
let spacing: CGFloat = 10
var offsetY: CGFloat = 0
var offsetX: CGFloat = spacing
rows.append(Row())
for attribute in attributes {
let neededWidth = CGFloat(attribute.frame.width) + spacing
let neededMaxX = offsetX + neededWidth
if neededMaxX <= collectionViewWidth {
attribute.frame.origin.x = offsetX
attribute.frame.origin.y = offsetY
offsetX = neededMaxX
rows.last?.add(attribute: attribute)
} else {
attribute.frame.origin.x = spacing
offsetX = attribute.frame.origin.x + neededWidth
offsetY += attribute.frame.height + spacing
attribute.frame.origin.y = offsetY
rows.append(Row())
rows.last?.add(attribute: attribute)
}
}
return rows.flatMap { $0.attributes }
}
}
class Row {
var attributes = [UICollectionViewLayoutAttributes]()
init() {}
func add(attribute: UICollectionViewLayoutAttributes) {
attributes.append(attribute)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.