Skip to content

Instantly share code, notes, and snippets.

@stulevine
Last active April 22, 2017 20:14
Show Gist options
  • Save stulevine/b90856bc4087c6f98dc36af220193928 to your computer and use it in GitHub Desktop.
Save stulevine/b90856bc4087c6f98dc36af220193928 to your computer and use it in GitHub Desktop.
Expanding Pill with Number in Swift 3.1
//: Playground - noun: a place where people can play
import UIKit
import PlaygroundSupport
extension UIColor {
class func with(hex: UInt, alpha: Float = 1.0) -> UIColor {
return UIColor(colorLiteralRed: Float((hex & 0xFF0000) >> 16)/255.0,
green: Float((hex & 0x00FF00) >> 8)/255.0,
blue: Float((hex & 0x0000FF) >> 0)/255.0,
alpha: alpha)
}
}
extension UIView {
func pinEdges(toView view: UIView, edges: [NSLayoutAttribute] = [.top, .bottom, .left, .right], insets: UIEdgeInsets = .zero) {
for edge in edges {
switch edge {
case .top:
self.topAnchor.constraint(equalTo: view.topAnchor,
constant: insets.top).isActive = true
case .bottom:
self.bottomAnchor.constraint(equalTo: view.bottomAnchor,
constant: -insets.bottom).isActive = true
case .left:
self.leftAnchor.constraint(equalTo: view.leftAnchor,
constant: insets.left).isActive = true
case .right:
self.rightAnchor.constraint(equalTo: view.rightAnchor,
constant: -insets.right).isActive = true
default:
print("Only left, right, top bottom attributes supported.")
}
}
}
}
class Overlay: UIView {
override func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
context?.saveGState()
context?.setStrokeColor(UIColor.with(hex: 0xF0F0F0).withAlphaComponent(0.75).cgColor)
context?.setLineWidth(2.0)
context?.setLineDash(phase: 0, lengths: [2])
context?.move(to: CGPoint(x: rect.width / 2, y: 0))
context?.addLine(to: CGPoint(x: rect.width / 2, y: rect.height))
context?.move(to: CGPoint(x: 0, y: rect.height / 2))
context?.addLine(to: CGPoint(x: rect.width, y: rect.height / 2))
context?.strokePath()
context?.restoreGState()
}
}
class NumberDotView: UIView {
var verticalConstraint = NSLayoutConstraint()
lazy var label: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textAlignment = .center
label.textColor = UIColor.white
return label
}()
lazy var overlay: Overlay = {
let overlayView = Overlay()
overlayView.translatesAutoresizingMaskIntoConstraints = false
overlayView.backgroundColor = UIColor.clear
return overlayView
}()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
init() {
super.init(frame: .zero)
commonInit()
}
init(radius: CGFloat,
fillColor: UIColor = UIColor.with(hex: 0xE01010),
textColor: UIColor = UIColor.white,
showCrossHairOverlay: Bool = false) {
super.init(frame: .zero)
backgroundColor = fillColor
label.textColor = textColor
commonInit(isOverlayHidden: !showCrossHairOverlay)
layer.cornerRadius = radius
}
override func updateConstraints() {
super.updateConstraints()
if layer.cornerRadius == 0 {
layer.cornerRadius = frame.width / 2
}
overlay.setNeedsDisplay()
verticalConstraint.constant = label.font.capHeight / 2
}
func commonInit(isOverlayHidden: Bool = true) {
overlay.isHidden = isOverlayHidden
clipsToBounds = true
addSubview(label)
addSubview(overlay)
overlay.pinEdges(toView: self)
verticalConstraint = label.firstBaselineAnchor.constraint(equalTo: centerYAnchor)
verticalConstraint.isActive = true
label.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
}
}
let view = UIView(frame: CGRect(x: 50, y: 50, width: 300, height: 600))
let radius: CGFloat = 15
let diameter = 2 * radius
var yOffset: CGFloat = diameter
let numbers = [3, 5, 10, 120, 1359, 24005, 50, 16, 733, 8888, 999, 90982131]
for num in numbers {
let dot = NumberDotView(radius: radius)
let numStr = String(describing: num)
var pillWidth = diameter
dot.translatesAutoresizingMaskIntoConstraints = false
dot.label.font = UIFont.boldSystemFont(ofSize: diameter * 0.5)
dot.label.text = numStr
if numStr.characters.count > 2 {
pillWidth += CGFloat(numStr.characters.count) * dot.label.font.xHeight
}
view.addSubview(dot)
dot.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
dot.centerYAnchor.constraint(equalTo: view.topAnchor, constant: yOffset).isActive = true
dot.widthAnchor.constraint(equalToConstant: pillWidth).isActive = true
dot.heightAnchor.constraint(equalToConstant: diameter).isActive = true
yOffset += diameter + 5
}
view.backgroundColor = UIColor.white
PlaygroundPage.current.liveView = view
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment