ios - 当单元格具有动态宽度时,CollectionView 中的间距不正确?
问题描述
我想实现一个 TokenView(芯片视图)样式的视图。为此,我在 UITableViewCell 内使用集合视图,CollectionView 有自定义单元格。在自定义单元格内有UILabel
. 现在单元格的宽度取决于UILabel
.
下面是自定义 UITableViewCell Cell 的代码
import UIKit
class LanguageTableViewCell: UITableViewCell,UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout{
var arr:[String] = ["English","Intermediate","English","Intermediate","English","Intermediate","English","Intermediate","English","Intermediate","English","Intermediate","English","Intermediate","English","Intermediate","English","Intermediate","English","Intermediate","English","Intermediate"]
@IBOutlet weak var collectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
collectionView.dataSource = self
collectionView.delegate = self
let layout = UICollectionViewFlowLayout()
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
layout.scrollDirection = .vertical
self.collectionView.collectionViewLayout = layout
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return arr.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: "LanguageCollectionViewCell", for: indexPath) as! LanguageCollectionViewCell
cell.setValue(lang: arr[indexPath.row],indexPath:indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let string = arr[indexPath.row]
let width = (string.count * 10)
return CGSize(width:width, height: 30)
}
}
类UICollectionViewCell
typealias Parameters = [String:Any]
import UIKit
class LanguageCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var languageLabel: UILabel!
override func layoutSubviews() {
super.layoutSubviews()
}
func setValue(lang:String ,indexPath:IndexPath) {
if indexPath.row % 2 == 0 {
languageLabel.backgroundColor = UIColor.gray
}else {
languageLabel.backgroundColor = UIColor.yellow
}
self.languageLabel.text = lang
}
}
解决方案
在你的UITableViewCell Cell
- 子类化
UICollectionViewFlowLayout
- 添加这样的实现:
解决方案是减少单元格间距/对齐 UICollectionView 单元格布局。非常简单和快速的性能。基于Olloqui给出的例子
类 CustomViewFlowLayout
class CustomViewFlowLayout: UICollectionViewFlowLayout {
let cellSpacing:CGFloat = 4
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
self.minimumLineSpacing = 4.0
self.sectionInset = UIEdgeInsets(top: 10, left: 8, bottom: 10, right: 6)
let attributes = super.layoutAttributesForElements(in: rect)
var leftMargin = sectionInset.left
var maxY: CGFloat = -1.0
attributes?.forEach { layoutAttribute in
if layoutAttribute.frame.origin.y >= maxY {
leftMargin = sectionInset.left
}
layoutAttribute.frame.origin.x = leftMargin
leftMargin += layoutAttribute.frame.width + cellSpacing
maxY = max(layoutAttribute.frame.maxY , maxY)
}
return attributes
}
}
其中 cellSpacing 可以设置为您喜欢的任何值。这个技巧保证单元格之间的空间将完全等于 cellSpacing。
UITableViewCell Cell/CollectionViewController 的实现。
import UIKit
class ViewController: UIViewController , UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout{
@IBOutlet weak var collectionView: UICollectionView!
var arr:[String] = ["English","Intermediate","English","English","arr","UICollectionViewFlowLayoutFlowFlowFlow","English","UICollectionViewDelegate","English","Intermediate","UIViewController","viewDidLoad","Intermediate","String","Intermediate","arr","Intermediate","UIKit","Intermediate","English","columnLayout","English","languageLabel"]
let columnLayout = CustomViewFlowLayout()
override func viewDidLoad() {
super.viewDidLoad()
collectionView.collectionViewLayout = columnLayout
collectionView.contentInsetAdjustmentBehavior = .always
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return arr.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "chip", for: indexPath) as! LanguageCollectionViewCell
cell.languageLabel.text = arr[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let string = arr[indexPath.row]
// your label font.
let font = UIFont.systemFont(ofSize: 16)
let fontAttribute = [NSAttributedStringKey.font: font]
// to get the exact width for label according to ur label font and Text.
let size = string.size(withAttributes: fontAttribute)
// some extraSpace give if like so.
let extraSpace : CGFloat = 8.0
let width = size.width + extraSpace
return CGSize(width:width, height: 30)
}
}
类UICollectionViewCell
class LanguageCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var languageLabel: UILabel!
}
推荐阅读
- docker - docker中的模拟时间(-compose)
- r - 在 R Shiny App 中延迟后更改输出
- machine-learning - 在现实世界中没有恒定平衡时如何平衡您的数据集
- php - 无论如何,SQlite3 是否知道已添加的条目数量?
- java - Java FX 与 Firebase 存储的连接,用于上传图片
- parsing - 使用 Wordpress 提要获取解析错误
- julia - “错误:语法:不能并列字符串文字”用引号结束三引号字符串文字时
- c# - 如何为 GPIO 启用 LightningProviders?
- c# - 当按下按钮并显示在另一个页面上时,试图从两个输入中更改标签?| Xamarin | C#
- r - 将 JSON 对象拆分为多个数据帧的更快方法?