Last active
August 29, 2015 14:17
-
-
Save Ridwy/8a2093de88384152b55d to your computer and use it in GitHub Desktop.
User icon lining up view like FourSquare
This file contains hidden or 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
// | |
// CNLiningUpView.swift | |
// CNLiningUpView | |
// | |
// Created by Chiharu Nameki on 2015/03/29. | |
// Copyright (c) 2015 Chiharu Nameki. All rights reserved. | |
// | |
import UIKit | |
class CNLiningUpItem { | |
let imageURL: NSURL? | |
let badgeImage: UIImage? | |
init(imageURL: NSURL? = nil, badgeImage: UIImage? = nil) { | |
self.imageURL = imageURL | |
self.badgeImage = badgeImage | |
} | |
} | |
class CNLiningUpItemView : UIView { | |
var imageView: UIImageView! | |
var badgeImageView: UIImageView! | |
override init(frame: CGRect) { | |
super.init(frame: frame) | |
setup() | |
} | |
required init(coder aDecoder: NSCoder) { | |
super.init(coder: aDecoder) | |
setup() | |
} | |
func setup() { | |
imageView = UIImageView(frame: bounds) | |
imageView.contentMode = .ScaleAspectFill | |
imageView.autoresizingMask = .FlexibleWidth | .FlexibleHeight | |
imageView.clipsToBounds = true | |
imageView.layer.cornerRadius = 2.0 | |
self.addSubview(imageView) | |
badgeImageView = UIImageView(frame: CGRectMake(-2, -2, 10, 10)) | |
badgeImageView.autoresizingMask = .FlexibleRightMargin | .FlexibleBottomMargin | |
self.addSubview(badgeImageView) | |
} | |
} | |
class CNLiningUpView : UIView { | |
required init(coder aDecoder: NSCoder) { | |
super.init(coder: aDecoder) | |
} | |
override init(frame: CGRect) { | |
super.init(frame: frame) | |
} | |
// data source | |
var items: [CNLiningUpItem] = [] | |
var count: Int = 0 | |
// appearances | |
var itemSize: CGSize = CGSizeMake(22, 22) | |
var itemPlaceholderImage: UIImage? | |
var margin: CGFloat = 4.0 | |
var showsMoreItem = true | |
var badgeFrame: CGRect = CGRectMake(-2, -2, 10, 10) | |
func reloadData() { | |
update() | |
for (i, itemView) in enumerate(itemViews) { | |
if itemView.superview == nil { | |
break | |
} | |
configureItemView(itemView, item:items[i]) | |
} | |
} | |
func generateItemView() -> UIView { | |
let view = CNLiningUpItemView(frame: CGRectMake(0, 0, itemSize.width, itemSize.height)) | |
view.badgeImageView.frame = badgeFrame | |
return view | |
} | |
func configureItemView(itemView: UIView, item: CNLiningUpItem) { | |
if let itemView = itemView as? CNLiningUpItemView { | |
itemView.imageView.sd_setImageWithURL(item.imageURL, | |
placeholderImage: itemPlaceholderImage, | |
options: .CacheMemoryOnly) | |
itemView.badgeImageView.image = item.badgeImage | |
} | |
} | |
func generateMoreItemView() -> UIView { | |
let label = UILabel(frame: CGRectMake(0, 0, itemSize.width, itemSize.height)) | |
label.font = UIFont.systemFontOfSize(itemSize.height * 0.38) | |
label.minimumScaleFactor = 0.5 | |
label.textColor = UIColor.whiteColor() | |
label.textAlignment = .Center | |
label.backgroundColor = UIColor.grayColor() | |
return label | |
} | |
func configureMoreItemView(number: Int) { | |
if let label = moreItemView as? UILabel { | |
label.text = number < 100 ? "+\(number)" : "+lots" | |
} | |
} | |
private var itemViews: [UIView] = [] | |
var moreItemView: UIView! | |
override func layoutSubviews() { | |
update() | |
} | |
private func update() { | |
let centerY = (bounds.size.height - itemSize.height) * 0.5 | |
let max = Int((bounds.size.width + margin) / (itemSize.width + margin)) | |
let needsMoreItem = { () -> Bool in | |
if self.showsMoreItem { | |
if self.items.count < self.count { | |
return true | |
} | |
if max < self.items.count { | |
return true | |
} | |
} | |
return false | |
}() | |
let n = min(min(items.count, count), max - (needsMoreItem ? 1 : 0)) | |
for i in 0..<n { | |
if itemViews.count <= i { | |
let itemView = generateItemView() | |
itemViews.append(itemView) | |
configureItemView(itemView, item: items[i]) | |
} | |
let view = itemViews[i] | |
view.frame = CGRectMake((itemSize.width + margin) * CGFloat(i), centerY, itemSize.width, itemSize.height) | |
if view.superview == nil { | |
addSubview(view) | |
} | |
} | |
if n < itemViews.count { | |
for i in n..<itemViews.count { | |
let view = itemViews[i] | |
view.removeFromSuperview() | |
} | |
} | |
if needsMoreItem { | |
if moreItemView == nil { | |
moreItemView = generateMoreItemView() | |
} | |
moreItemView.frame = CGRectMake((itemSize.width + margin) * CGFloat(n), centerY, itemSize.width, itemSize.height) | |
configureMoreItemView(count - n) | |
if moreItemView.superview == nil { | |
addSubview(moreItemView) | |
} | |
} else { | |
moreItemView?.removeFromSuperview() | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment