Skip to content

Instantly share code, notes, and snippets.

@stzn
Last active September 28, 2018 02:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stzn/8ccbbb90870b1a35630c0a716ab5251a to your computer and use it in GitHub Desktop.
Save stzn/8ccbbb90870b1a35630c0a716ab5251a to your computer and use it in GitHub Desktop.
// https://medium.com/halcyon-mobile/view-decoration-in-swift-4023a68be5d3
import UIKit
import PlaygroundSupport
protocol ViewDecorator {
associatedtype View: UIView
func decorate(view: View)
}
struct AnyViewDecorator<V> {
let _decorate: (V) -> Void
init<D: ViewDecorator>(decorator: D) where D.View == V {
_decorate = decorator.decorate
}
func decorate(view: V) {
_decorate(view)
}
}
extension UIView {
func decorate(with decorator: AnyViewDecorator<UIView>) {
decorator.decorate(view: self)
}
func decorate(with decorators: [AnyViewDecorator<UIView>]) {
decorators.forEach { $0.decorate(view: self) }
}
}
struct CornerRadiusViewDecorator: ViewDecorator {
let cornerRadius: CGFloat
func decorate(view: UIView) {
view.clipsToBounds = true
view.layer.cornerRadius = cornerRadius
}
}
struct ShadowViewDecorator: ViewDecorator {
let radius: CGFloat
func decorate(view: UIView) {
view.layer.shadowRadius = radius
view.layer.shadowOpacity = 0.3
view.layer.shadowColor = UIColor.black.cgColor
view.layer.shadowOffset = CGSize(width: 0, height: radius / 2)
view.layer.masksToBounds = false
}
}
struct CardViewDecorator: ViewDecorator {
private let decorators: [AnyViewDecorator<UIView>] = [
AnyViewDecorator(decorator: CornerRadiusViewDecorator(cornerRadius: 4)),
AnyViewDecorator(decorator: ShadowViewDecorator(radius: 2))
]
func decorate(view: UIView) {
view.decorate(with: decorators)
}
}
struct ButtonViewDecorator: ViewDecorator {
typealias View = UIButton
func decorate(view: UIButton) {
view.setTitleColor(.white, for: .normal)
view.setTitleShadowColor(.black, for: .normal)
view.titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 50)
}
}
struct LabelViewDecorator: ViewDecorator {
typealias View = UILabel
func decorate(view: UILabel) {
view.tintColor = .red
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.frame = CGRect(x: 0, y: 0, width: 320, height: 480)
self.view.backgroundColor = .white
let button = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
button.setTitle("OK", for: .normal)
button.backgroundColor = .blue
let cardDecorator = CardViewDecorator()
cardDecorator.decorate(view: button)
self.view.addSubview(button)
let button2 = UIButton(frame: CGRect(x: 100, y: 300, width: 100, height: 100))
button2.setTitle("NG", for: .normal)
button2.backgroundColor = .red
button2.decorate(with: [
AnyViewDecorator(decorator: CornerRadiusViewDecorator(cornerRadius: 10)),
AnyViewDecorator(decorator: ShadowViewDecorator(radius: 4))
])
self.view.addSubview(button2)
let button3 = UIButton(frame: CGRect(x: 100, y: 500, width: 100, height: 100))
button3.setTitle("Not", for: .normal)
button3.backgroundColor = .green
let buttonDecorator = ButtonViewDecorator()
buttonDecorator.decorate(view: button3)
self.view.addSubview(button3)
}
}
let viewController = ViewController()
PlaygroundPage.current.liveView = viewController
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment