我有一个任务,我要准备一个简单的GridView,几乎没有约束。我想过使用UICollectionView
并在网上做了一些研究。我发现了一篇博文here,其中的内容与我希望实现的类似。
现在,它使用customCollectionViewCell
类用于Rows&列。每个单元格中都有UILabel
。因此,UILabel
可以包含动态文本,单元格应根据UILabel
的动态调整其大小。
请找到以下所有代码 -
行单元格的 UICollectionView
class RowCell: UICollectionViewCell
{
var textLabel : UILabel!
override init(frame: CGRect)
{
super.init(frame: frame)
textLabel = UILabel(frame: CGRectMake(0, 0, 65, 35))
textLabel.font = UIFont.systemFontOfSize(UIFont.smallSystemFontSize())
textLabel.textAlignment = .Center
textLabel.numberOfLines = 0
textLabel.backgroundColor = UIColor.clearColor()
textLabel.lineBreakMode = NSLineBreakMode.ByCharWrapping
textLabel.sizeThatFits(CGSizeMake(self.bounds.width, self.bounds.height))
contentView.addSubview(textLabel)
self.layer.borderWidth = 0.7
self.layer.borderColor = charcoalColor.CGColor
self.frame = CGRectMake(frame.origin.x, frame.origin.y, textLabel.frame.width*8, textLabel.frame.height*8)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
列单元格 UICollectionView
class ColumnCell: UICollectionViewCell
{
var columnLabel : UILabel!
override init(frame: CGRect)
{
super.init(frame: frame)
columnLabel = UILabel()
columnLabel.frame = CGRectMake(0 ,0 ,65 ,35)
columnLabel.font = UIFont.systemFontOfSize(UIFont.smallSystemFontSize())
columnLabel.textAlignment = .Center
columnLabel.backgroundColor = UIColor.clearColor()
columnLabel.numberOfLines = 0
columnLabel.lineBreakMode = NSLineBreakMode.ByCharWrapping
columnLabel.sizeThatFits(CGSizeMake(self.bounds.width, self.bounds.height))
contentView.addSubview(columnLabel)
self.layer.borderWidth = 0.7
self.layer.borderColor = charcoalColor.CGColor
self.frame = CGRectMake(frame.origin.x, frame.origin.y, columnLabel.frame.width*8, columnLabel.frame.height*8)
}
func getDynamicHeight(ofLabel label: UILabel)->CGFloat
{
if(label.text == nil)
{
label.sizeToFit()
var maxLabelSize = CGSizeMake(label.bounds.size.width, CGFloat(MAXFLOAT))
var expectedSize = (label.text! as NSString).boundingRectWithSize(maxLabelSize, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName:label.font], context: nil).size
return expectedSize.height
}
return CGFloat(30)
}
required init(coder aDecoder: NSCoder)
{
fatalError("init(coder:) has not been implemented")
}
}
我的ViewController,我在其中创建CollectionView
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate
{
let columnCellIdentifier = "ColumnCellIdentifier"
let rowCellIdentifier = "RowCellIdentifier"
let arrayOfData = ["Tom", "Han", "Jerry", "Popye", "Bluto", "Elvis", "Vin", "PaulShankar Dharmawat", "Vishwanathan", "Belloweiss" ]
var collectionView: UICollectionView!
override func viewDidLoad()
{
super.viewDidLoad()
self.view.backgroundColor = UIColor.whiteColor()
collectionView = UICollectionView(frame: CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y + 20.0, self.view.frame.size.width, self.view.frame.size.height), collectionViewLayout: CustomCollectionViewLayout())
self.collectionView.delegate = self // delegate : UICollectionViewDelegate
self.collectionView.dataSource = self // datasource : UICollectionViewDataSource
self.collectionView.registerClass(ColumnCell.self, forCellWithReuseIdentifier: columnCellIdentifier)
self.collectionView.registerClass(RowCell.self, forCellWithReuseIdentifier: rowCellIdentifier)
self.collectionView.backgroundColor = UIColor.whiteColor()
self.view.addSubview(self.collectionView)
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
// MARK - UICollectionViewDataSource Methods
// This is number of rows that we want in table
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int
{
return 20
}
// This is number of columns that we want in table
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return 20
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
if indexPath.section == 0
{
if indexPath.row == 0
{
let columnCell : ColumnCell = collectionView.dequeueReusableCellWithReuseIdentifier(columnCellIdentifier, forIndexPath: indexPath) as! ColumnCell
columnCell.columnLabel.text = "⬇️ DATE / NAMES➡️"
return columnCell
}
else
{
// First Section -> row data
let rowCell : RowCell = collectionView .dequeueReusableCellWithReuseIdentifier(rowCellIdentifier, forIndexPath: indexPath) as! RowCell
if(indexPath.row < arrayOfData.count)
{
rowCell.textLabel.text = "\(arrayOfData[indexPath.row])"
}
else
{
rowCell.textLabel.text = "\([indexPath.section]),\([indexPath.row])"
}
if indexPath.section % 2 != 0
{
rowCell.backgroundColor = limeYellowColor
}
else
{
rowCell.backgroundColor = UIColor.whiteColor()
}
return rowCell
}
}
else
{
if indexPath.row == 0
{
let columnCell : ColumnCell = collectionView .dequeueReusableCellWithReuseIdentifier(columnCellIdentifier, forIndexPath: indexPath) as! ColumnCell
columnCell.columnLabel.text = "\(indexPath.section),\(indexPath.row)"
if indexPath.section % 2 != 0
{
columnCell.backgroundColor = limeYellowColor
}
else
{
columnCell.backgroundColor = UIColor.whiteColor()
}
return columnCell
}
else
{
let rowCell : RowCell = collectionView .dequeueReusableCellWithReuseIdentifier(rowCellIdentifier, forIndexPath: indexPath) as! RowCell
rowCell.textLabel.text = "I am a rockstar yo yo baby"
if indexPath.section % 2 != 0
{
rowCell.backgroundColor = limeYellowColor
}
else
{
rowCell.backgroundColor = UIColor.whiteColor()
}
return rowCell
}
}
}
// MARK - UICollectionViedDelegate Methods
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
println(indexPath.section, indexPath.row)
}
// MARK - Private Methods
func getMaxLengthOfTextFromArrayOfData() -> Int
{
var maxLength = 0
for item in self.arrayOfData
{
if(maxLength < count(item))
{
maxLength = count(item)
}
}
println("MaxLength is \(maxLength)")
return maxLength
}
}
UICollectionViewLayout
子类
class CustomCollectionViewLayout: UICollectionViewLayout
{
// The following code is only executed the first time we prepare the layout
var numberOfColumns = 0
var itemAttributes : NSMutableArray!
var itemsSize : NSMutableArray!
var contentSize : CGSize!
var dataForItems : NSMutableArray!
override func prepareLayout()
{
println("prepareLayout")
if self.collectionView?.numberOfSections() == 0
{
return
}
var tempVar = self.collectionView?.numberOfItemsInSection(0)
numberOfColumns = tempVar!
// Creating layout attributes of each item by looping though the numberOfItems
if (self.itemAttributes != nil && self.itemAttributes.count > 0)
{
for section in 0..<self.collectionView!.numberOfSections()
{
var numberOfItems : Int = self.collectionView!.numberOfItemsInSection(section)
for index in 0..<numberOfItems
{
if section != 0 && index != 0
{
continue
}
var attributes : UICollectionViewLayoutAttributes = self.layoutAttributesForItemAtIndexPath(NSIndexPath(forItem: index, inSection: section))
}
}
return
}
// Calculating the item Size
if (self.itemsSize == nil || self.itemsSize.count != numberOfColumns)
{
self.calculateItemsSize()
}
var column = 0
var xOffset : CGFloat = 0
var yOffset : CGFloat = 0
var contentWidth : CGFloat = 0
var contentHeight : CGFloat = 0
// We loop through all items
for section in 0..<self.collectionView!.numberOfSections()
{
var sectionAttributes = NSMutableArray()
for index in 0..<numberOfColumns
{
println("ItemSize - \(self.itemsSize)")
var itemSize = self.itemsSize[index].CGSizeValue()
var indexPath = NSIndexPath(forItem: index, inSection: section)
var attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)
attributes.frame = CGRectIntegral(CGRectMake(xOffset, yOffset, itemSize.width, itemSize.height))
// setting the zIndex of attributes
if section == 0 && index == 0
{
attributes.zIndex = 1024;
}
else if section == 0 || index == 0
{
attributes.zIndex = 1023
}
if section == 0
{
var frame = attributes.frame
frame.origin.y = self.collectionView!.contentOffset.y
attributes.frame = frame
}
if index == 0
{
var frame = attributes.frame
frame.origin.x = self.collectionView!.contentOffset.x
attributes.frame = frame
}
sectionAttributes.addObject(attributes)
xOffset += itemSize.width
column++
if column == numberOfColumns
{
if xOffset > contentWidth
{
contentWidth = xOffset
}
column = 0
xOffset = 0
yOffset += itemSize.height
}
}
if (self.itemAttributes == nil)
{
self.itemAttributes = NSMutableArray(capacity: self.collectionView!.numberOfSections())
}
self.itemAttributes .addObject(sectionAttributes)
}
var attributes : UICollectionViewLayoutAttributes = self.itemAttributes.lastObject?.lastObject as! UICollectionViewLayoutAttributes
contentHeight = attributes.frame.origin.y + attributes.frame.size.height
self.contentSize = CGSizeMake(contentWidth, contentHeight)
}
override func collectionViewContentSize() -> CGSize
{
println("collectionViewContentSize")
return self.contentSize
}
override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes!
{
println("layoutAttributesForItemAtIndexPath")
return self.itemAttributes[indexPath.section][indexPath.row] as! UICollectionViewLayoutAttributes
}
override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]?
{
println("layoutAttributesForElementsInRect")
var attributes : NSMutableArray = NSMutableArray()
for section in self.itemAttributes
{
attributes.addObjectsFromArray(
section.filteredArrayUsingPredicate(
NSPredicate(block: { (evaluatedObject, bindings) -> Bool in
return CGRectIntersectsRect(rect, evaluatedObject.frame)
})
)
)
}
return attributes as [AnyObject]
}
override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool
{
println("shouldInvalidateLayoutForBoundsChange")
return true
}
// MARK : Private Methods
func sizeForItemWithColumnIndex(columnIndex: Int) -> CGSize
{
println("sizeForItemWithColumnIndex")
var text : String = ""
switch (columnIndex)
{
case 0:
text = "Col 0"
case 1:
text = "Col 1"
case 2:
text = "Col 2"
case 3:
text = "Col 3"
case 4:
text = "Col 4"
case 5:
text = "Col 5"
case 6:
text = "Col 6"
default:
text = "Col 7"
// HOW DO I GET THE MAX SIZE OF COLUMN CELLs HERE, SO THAT I CAN FIX THE WIDTH OF THE ENTIRE COLUMN?
}
var size : CGSize = (text as NSString).sizeWithAttributes([NSFontAttributeName: UIFont.systemFontOfSize(17.0)])
let width : CGFloat = size.width + 25
println("ItemSize - \(self.itemsSize)")
return CGSizeMake(width, 40)
}
func calculateItemsSize()
{
println("calculateItemsSize")
self.itemsSize = NSMutableArray(capacity: numberOfColumns)
// Storing the calculated sizes in itemsSize array in order to do the calculations only once per column.
for index in 0..<numberOfColumns
{
self.itemsSize.addObject(NSValue(CGSize: self.sizeForItemWithColumnIndex(index)))
}
}
}
我的问题 -
如何设置UICollectionViewCell
(ColumnCell)大小取决于其中UIlabel
的动态大小?
答案 0 :(得分:2)
您需要跟踪每个网格列的宽度。当标签动态更改并变得大于当前宽度时,请调用invalidateLayout
,以便列中的单元格可以自行调整大小。