Created
June 3, 2017 10:09
-
-
Save nunogoncalves/5df6502b3178d0ce1d766c87ed43f7c4 to your computer and use it in GitHub Desktop.
Easily apply theme styles to any UIView!
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
Make the following possible! | |
MarvelTheme.TextStyle.CommicSans.apply(to: label) | |
MarvelTheme.ColorStyle.dangerColor.apply(to: label) | |
// ============================== StylableView protocol ============================== | |
// Adds a consistent styling API to any UIView. | |
// The example here allows for any UIView subclass to have a way of setting its font type. | |
protocol StylableView { | |
func apply(font: UIFont?) | |
} | |
extension UIView : StylableView { | |
//we can't really add this as a StylableView extension because | |
//the views are being styled as StylableView, and even if the subclasses | |
//override the default implementation, they won't be recognized. | |
func apply(font: UIFont?) {} | |
} | |
extension UILabel { | |
override func apply(font: UIFont?) { | |
self.font = font | |
} | |
} | |
extension UIButton { | |
override func apply(font: UIFont?) { | |
titleLabel?.font = font | |
} | |
} | |
//Now we have a consistent way of setting font of both labels and buttons. | |
struct UIViewStyle { | |
let styling: (StylableView) -> () | |
func apply(to stylabelView: StylableView) { | |
styling(stylabelView) | |
} | |
static func compose(styles: UIViewStyle...) -> UIViewStyle { | |
return UIViewStyle { | |
for style in styles { | |
style.apply(to: $0) | |
} | |
} | |
} | |
} | |
// Basic example view | |
let whiteStyle = UIViewStyle { ($0 as? UIView)?.backgroundColor = .white } //We can improve this with a consistent API | |
let blueStyle = UIViewStyle { ($0 as? UIView)?.backgroundColor = .blue } | |
let v = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) | |
whiteStyle.apply(to: v) | |
v // background becomes white | |
blueStyle.apply(to: v) | |
v // background becomes blue | |
let h1 = UIViewStyle { $0.apply(font: UIFont(name: "ComicSansRegular", size: 10)) } | |
h1.apply(to: UIView()) //Does nothing because the UIView method is empty. | |
h1.apply(to: UILabel() //Applies the CommicSansRegular font to the label | |
============================== Theming ============================== | |
protocol ColorStylable { | |
static var mainColor: UIViewStyle { get } | |
} | |
protocol TextStylable { | |
static var mainColor: UIViewStyle { get } | |
} | |
protocol Themable { | |
static var ColorStyle: ColorStylable.Type { get } | |
static var TextStyle: TextStylable.Type { get } | |
} | |
struct MarvelColorStyle : ColorStylable { | |
static let mainColor = UIViewStyle { ($0 as? UIView)?.backgroundColor = .red } | |
} | |
struct MarvelTextStyle: TextStylable {} | |
struct MarvelTheme : Themable { | |
static var TextStyle: TextStylable.Type = MarvelTextStyle.self | |
static var ColorStyle: ColorStylable.Type = MarvelColorStyle.self | |
} | |
let theme = MarvelTheme.self | |
theme.ColorStyle.mainColor.apply(to: v) | |
v | |
============================================ Examples ===================================== | |
let courierNewPSBold = UIViewStyle { $0.apply(font: UIFont(name: "CourierNewPS-BoldMT", size: 15)) } | |
let papyrus = UIViewStyle { $0.apply(font: UIFont(name: "Papyrus-Condensed", size: 20)) } | |
let blueText = UIViewStyle { $0.apply(textColor: .blue) } | |
let greenText = UIViewStyle { $0.apply(textColor: .green) } | |
let courierNewPSBoldBlue = UIViewStyle.compose(styles: courierNewPSBold, blueText) | |
let papyrusGreen = UIViewStyle.compose(styles: papyrus, greenText) | |
let label = UILabel() | |
v.addSubview(label) | |
label.text = "Some text" | |
label.frame = CGRect(x: 10, y: 10, width: 80, height: 80) | |
courierNewPSBoldBlue.apply(to: label) | |
v | |
papyrusGreen.apply(to: label) | |
v | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment