Created
January 9, 2015 15:41
-
-
Save codetalks-new/210c5f687d2d6db4b138 to your computer and use it in GitHub Desktop.
demo for simple Custom UICollectionViewFlowLayout with decoratorView
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Playground - noun: a place where people can play | |
import UIKit | |
extension UIColor{ | |
convenience init(hex:Int){ | |
let red = CGFloat((hex >> 16) & 0xff) / 255.0 | |
let green = CGFloat((hex >> 8) & 0xff) / 255.0 | |
let blue = CGFloat( hex & 0xff) / 255.0 | |
self.init(red:red,green:green,blue:blue,alpha:1) | |
} | |
} | |
let textSource = [ | |
"是故意的吗" | |
,"是我得罪谁了吗" | |
,"这一天竟然每件事情都失算" | |
,"只想转个弯" | |
,"却绕到了飞机场" | |
,"发现没钱在身上" | |
,"乌云乌云快走开" | |
] | |
func choice<T>(arr:[T]) -> T{ | |
return arr[ random() % arr.count ] | |
} | |
func demoTitle() ->String { | |
return choice(textSource) | |
} | |
func demoSummary() -> String{ | |
var maxCount = random() % 5 + 2 | |
var sumary = "" | |
while maxCount > 0{ | |
sumary += choice(textSource) | |
maxCount-- | |
} | |
return sumary | |
} | |
class Topic{ | |
var title="" | |
var summary = "" | |
init(title:String,summary:String){ | |
self.title = title | |
self.summary = summary | |
} | |
convenience init(){ | |
self.init(title:demoTitle(),summary:demoSummary()) | |
} | |
} | |
let redColor = UIColor(hex: 0xda1c5c) | |
let blueColor = UIColor(hex: 0x117fbb) | |
let greenColor = UIColor(hex: 0x169f8c) | |
let colors = [ redColor,blueColor,greenColor ] | |
let secondaryTextColor = UIColor(hex: 0xb6b6b6) | |
let backgroundColor = UIColor(hex: 0xefefef) | |
func primaryColor() -> UIColor{ | |
return colors[ random() % colors.count ] | |
} | |
class TopicView:UICollectionViewCell{ | |
let title = UILabel() | |
let summary = UILabel() | |
class var identifier:String{ | |
return "TopicView" | |
} | |
override init(frame: CGRect) { | |
super.init(frame: frame) | |
setup() | |
} | |
required init(coder aDecoder: NSCoder) { | |
fatalError("init(coder:) has not been implemented") | |
} | |
func setup(){ | |
contentView.layer.borderWidth = 1 | |
contentView.layer.cornerRadius = 8 | |
contentView.backgroundColor = UIColor.whiteColor() | |
contentScaleFactor = 2 | |
contentView.contentScaleFactor = 2 | |
title.contentScaleFactor = 2 | |
title.font = UIFont.italicSystemFontOfSize(14) | |
title.numberOfLines = 1 | |
title.lineBreakMode = .ByTruncatingTail | |
summary.textColor = secondaryTextColor | |
summary.font = UIFont.systemFontOfSize(12) | |
summary.numberOfLines = 2 | |
summary.lineBreakMode = .ByTruncatingTail | |
contentView.addSubview(title) | |
contentView.addSubview(summary) | |
title.setTranslatesAutoresizingMaskIntoConstraints(false) | |
summary.setTranslatesAutoresizingMaskIntoConstraints(false) | |
let sbConstraint = NSLayoutConstraint(item: summary, attribute: .Bottom, relatedBy: .Equal, toItem: contentView, attribute: .Bottom, multiplier: 1, constant: -8) | |
let slConstraint = NSLayoutConstraint(item: summary, attribute: .Leading, relatedBy: .Equal, toItem: contentView, attribute: .Leading, multiplier: 1, constant: 8) | |
let srConstraint = NSLayoutConstraint(item: summary, attribute:.Trailing , relatedBy: .Equal, toItem: contentView, attribute: .Trailing, multiplier: 1, constant: -8) | |
let tbConstraint = NSLayoutConstraint(item: title, attribute: .Bottom, relatedBy: .Equal, toItem: summary, attribute: .Top, multiplier: 1, constant: -8) | |
let tlConstraint = NSLayoutConstraint(item: title, attribute: .Leading, relatedBy: .Equal, toItem: summary, attribute: .Leading, multiplier: 1, constant: 0) | |
let trConstraint = NSLayoutConstraint(item: title, attribute: .Trailing, relatedBy: .Equal, toItem: contentView, attribute: .Trailing, multiplier: 1, constant: -20) | |
contentView.addConstraint(sbConstraint) | |
contentView.addConstraint(slConstraint) | |
contentView.addConstraint(srConstraint) | |
contentView.addConstraint(tbConstraint) | |
contentView.addConstraint(tlConstraint) | |
contentView.addConstraint(trConstraint) | |
} | |
func bind(topic:Topic){ | |
title.text = topic.title | |
summary.text = topic.summary | |
let color = primaryColor() | |
title.textColor = color | |
contentView.layer.borderColor = color.CGColor | |
contentView.layoutIfNeeded() | |
} | |
} | |
// debug TopicView | |
//let topicView = TopicView(frame: CGRect(x: 0, y: 0, width: 240, height: 80)) | |
//topicView.bind(Topic()) | |
class TopicDataSource :NSObject,UICollectionViewDataSource{ | |
var topics:[Topic] = [] | |
override init() { | |
super.init() | |
generateDemoData() | |
} | |
func generateDemoData(){ | |
var maxCount = random() % 1 + 3 | |
while maxCount > 0 { | |
topics.append(Topic()) | |
maxCount-- | |
} | |
} | |
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int{ | |
return topics.count | |
} | |
// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath: | |
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell{ | |
let topicView = collectionView.dequeueReusableCellWithReuseIdentifier(TopicView.identifier, forIndexPath: indexPath) as TopicView | |
topicView.bind(topicAtIndexPath(indexPath)) | |
return topicView | |
} | |
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int{ | |
return 1 | |
} | |
// MARK: Helper | |
func topicAtIndexPath(indexPath:NSIndexPath) -> Topic{ | |
return topics[indexPath.item] | |
} | |
} | |
class SeperatorView: UICollectionReusableView { | |
override init(frame: CGRect) { | |
super.init(frame: frame) | |
setup() | |
} | |
required init(coder aDecoder: NSCoder) { | |
fatalError("init(coder:) has not been implemented") | |
} | |
func setup(){ | |
backgroundColor = primaryColor() | |
} | |
} | |
class TopicFlowLayout:UICollectionViewFlowLayout{ | |
struct LayoutKinds { | |
static let globalHeader = "globalHeader" | |
static let seperator = "seperator" | |
} | |
var seperatorLayoutInfo:[NSIndexPath:UICollectionViewLayoutAttributes] = [:] | |
override func prepareLayout() { | |
super.prepareLayout() | |
registerClass(SeperatorView.classForCoder(), forDecorationViewOfKind: LayoutKinds.seperator) | |
sectionInset = UIEdgeInsets(top: 36, left: 20, bottom: 36, right: 20) | |
itemSize = CGSize(width: collectionView!.bounds.width - 40, height: 96) | |
var layoutInfo:[NSIndexPath:UICollectionViewLayoutAttributes] = [:] | |
let sections = collectionView!.numberOfSections() | |
for section in Range(start: 0, end: sections){ | |
let items = collectionView!.numberOfItemsInSection(section) | |
for item in Range(start: 0, end: items){ | |
// ignoreLast | |
if item == (items - 1){ | |
continue | |
} | |
let indexPath = NSIndexPath(forItem: item, inSection: section) | |
layoutInfo[indexPath] = layoutAttributesForSeperatorAtIndexPath(indexPath) | |
} | |
} | |
seperatorLayoutInfo = layoutInfo | |
println("prepareLayout") | |
} | |
override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? { | |
var attrsArray = super.layoutAttributesForElementsInRect(rect) | |
for attrs in seperatorLayoutInfo.values{ | |
if attrs.frame.intersects(rect){ | |
attrsArray?.append(attrs) | |
} | |
} | |
return attrsArray | |
} | |
override func layoutAttributesForDecorationViewOfKind(elementKind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes! { | |
return seperatorLayoutInfo[indexPath] | |
} | |
// MARK:Helpers | |
func layoutAttributesForSeperatorAtIndexPath(indexPath:NSIndexPath) -> UICollectionViewLayoutAttributes{ | |
let cellAttributes = layoutAttributesForItemAtIndexPath(indexPath) | |
let nextIndexPath = NSIndexPath(forItem: indexPath.item + 1, inSection: indexPath.section) | |
let nextCellAttributes = layoutAttributesForItemAtIndexPath(nextIndexPath) | |
var layoutAttributes = UICollectionViewLayoutAttributes(forDecorationViewOfKind: LayoutKinds.seperator, withIndexPath: indexPath) | |
let strokeWidth:CGFloat = 2; | |
let baseFrame = cellAttributes.frame | |
let lineSpacing = nextCellAttributes.frame.minY - baseFrame.maxY | |
let y = baseFrame.maxY + (lineSpacing - strokeWidth ) * 0.5 | |
let frame = CGRect(x: baseFrame.origin.x, y: y, width: baseFrame.width, height: strokeWidth) | |
layoutAttributes.frame = frame | |
return layoutAttributes | |
} | |
} | |
let dataSource = TopicDataSource() | |
let layout = TopicFlowLayout() | |
let frame = CGRect(x: 0, y: 0, width: 320, height: 480) | |
let collectionView = UICollectionView(frame: frame, collectionViewLayout: layout) | |
collectionView.registerClass(TopicView.classForCoder(), forCellWithReuseIdentifier: TopicView.identifier) | |
collectionView.backgroundColor = backgroundColor | |
collectionView.dataSource = dataSource | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment