Last active
February 21, 2018 17:51
-
-
Save unnamedd/40d29659584fdd0fb86f45f81cbf8900 to your computer and use it in GitHub Desktop.
Extension UIView to add borders in partnership with @diegoventura and @brunogb
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
import UIKit | |
import PlaygroundSupport | |
extension UIView { | |
private class UIViewNamed: UIView { | |
var name: String | |
var thickness: CGFloat? = nil | |
required init(frame: CGRect = CGRect.zero, name: String) { | |
self.name = name | |
super.init(frame: frame) | |
} | |
required init?(coder aDecoder: NSCoder) { | |
fatalError("init(coder:) has not been implemented") | |
} | |
} | |
public enum RectEdge: String { | |
case top | |
case right | |
case bottom | |
case left | |
} | |
open func set(to edge: RectEdge, with color: UIColor, thickness: CGFloat? = nil) { | |
let view = self.border(to: edge) ?? UIViewNamed(name: edge.rawValue) | |
let thicknessToApply = thickness ?? view.thickness ?? 1.0 | |
view.backgroundColor = color | |
view.translatesAutoresizingMaskIntoConstraints = false | |
view.thickness = thicknessToApply | |
self.removeConstraints(view.constraints) | |
self.addSubview(view) | |
self.constraint(to: view, edge: edge, thickness: thicknessToApply) | |
} | |
private func border(to edge: RectEdge) -> UIViewNamed? { | |
let index = self.subviews.index(where: { | |
if $0 is UIViewNamed, let view = $0 as? UIViewNamed, view.name == edge.rawValue { | |
return true | |
} | |
return false | |
}) | |
guard let i = index else { | |
return nil | |
} | |
return self.subviews[i] as? UIViewNamed | |
} | |
private func constraint(to view: UIView, edge: RectEdge, thickness: CGFloat) { | |
switch edge { | |
case .top: | |
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-(0)-[top(==thickness)]", | |
options: [], | |
metrics: ["thickness": thickness], | |
views: ["top": view])) | |
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-(0)-[top]-(0)-|", | |
options: [], | |
metrics: nil, | |
views: ["top": view])) | |
break | |
case .right: | |
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[right(==thickness)]-(0)-|", | |
options: [], | |
metrics: ["thickness": thickness], | |
views: ["right": view])) | |
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-(0)-[right]-(0)-|", | |
options: [], | |
metrics: nil, | |
views: ["right": view])) | |
break | |
case .bottom: | |
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[bottom(==thickness)]-(0)-|", | |
options: [], | |
metrics: ["thickness": thickness], | |
views: ["bottom": view])) | |
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-(0)-[bottom]-(0)-|", | |
options: [], | |
metrics: nil, | |
views: ["bottom": view])) | |
break | |
case .left: | |
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-(0)-[left(==thickness)]", | |
options: [], | |
metrics: ["thickness": thickness], | |
views: ["left": view])) | |
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-(0)-[left]-(0)-|", | |
options: [], | |
metrics: nil, | |
views: ["left": view])) | |
break | |
} | |
} | |
} | |
class ViewController : UIViewController { | |
var sub: UIView? | |
func more() { | |
var frame = sub?.frame | |
frame?.size.height += 25 | |
sub?.frame = frame! | |
} | |
func less() { | |
var frame = sub?.frame | |
frame?.size.height -= 25 | |
sub?.frame = frame! | |
} | |
override func loadView() { | |
let view = UIView() | |
let more = UIButton(frame: CGRect(x: 135, y: 120, width: 40, height: 20)) | |
more.setTitle("+", for: .normal) | |
more.addTarget(self, action: #selector(self.more), for: .touchUpInside) | |
more.backgroundColor = .gray | |
view.addSubview(more) | |
let less = UIButton(frame: CGRect(x: more.frame.maxX + 10, y: more.frame.minY, width: 40, height: 20)) | |
less.setTitle("-", for: .normal) | |
less.addTarget(self, action: #selector(self.less), for: .touchUpInside) | |
less.backgroundColor = .lightGray | |
view.addSubview(less) | |
sub = UIView(frame: CGRect(x: more.frame.minX, y: more.frame.maxY + 10, width: 90, height: 50)) | |
sub?.backgroundColor = .green | |
sub?.set(to: .bottom, with: UIColor.gray, thickness: 5) | |
view.addSubview(sub!) | |
view.backgroundColor = UIColor.white | |
self.view = view | |
} | |
} | |
PlaygroundPage.current.liveView = ViewController() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
We can change the UIViewNamed, and add a thickness attribute:
and then on method set(border: we can change it to:
what do you think?