Last active
February 7, 2021 15:28
-
-
Save Anatoli-Petrosyants/3f27eae4fab56b9a7b279c5314e3c964 to your computer and use it in GitHub Desktop.
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
import Foundation | |
import UIKit | |
struct BaseStyles { | |
static func rounded<V: UIView>(cornerRadius r: CGFloat = 5.5) -> UIViewStyle<V> { | |
return UIViewStyle<V>(styling: { (view: V) in | |
view.layer.masksToBounds = true | |
view.clipsToBounds = true | |
view.layer.cornerRadius = r | |
}) | |
} | |
static func border<V: UIView>(width: CGFloat = 1.0, color: UIColor = .black) -> UIViewStyle<V> { | |
return UIViewStyle<V>(styling: { (view: V) in | |
view.layer.borderColor = color.cgColor | |
view.layer.borderWidth = width | |
}) | |
} | |
static func rounded<V: UIView>(corners: UIRectCorner, cornerRadius: CGFloat = 8.0) -> UIViewStyle<V> { | |
return UIViewStyle<V>(styling: { view in | |
let rectShape = CAShapeLayer() | |
rectShape.bounds = view.frame | |
rectShape.position = view.center | |
rectShape.path = UIBezierPath(roundedRect: view.bounds, | |
byRoundingCorners: corners, | |
cornerRadii: CGSize(width: cornerRadius, height: cornerRadius)).cgPath | |
view.layer.mask = rectShape | |
view.layer.masksToBounds = true | |
}) | |
} | |
static func circle<V: UIView>() -> UIViewStyle<V> { | |
return BaseStyles.rounded().composing(with: { (v) in | |
v.layer.cornerRadius = v.frame.size.height / 2 | |
}) | |
} | |
static let card: UIViewStyle<UIView> = rounded(cornerRadius: 5.5).composing { view in | |
view.layer.shadowOffset = CGSize(width: 0, height: 2.5) | |
shadow.styling(view) | |
} | |
static let shadow: UIViewStyle<UIView> = UIViewStyle { view in | |
view.layer.shadowColor = UIColor.gray.cgColor | |
view.layer.shadowOpacity = 0.15 | |
view.layer.shadowRadius = 2 | |
view.layer.masksToBounds = false | |
} | |
static let background: UIViewStyle<UIView> = UIViewStyle { view in | |
view.backgroundColor = .white | |
} | |
static let separator: UIViewStyle<UIView> = UIViewStyle { view in | |
view.backgroundColor = .lightGrey | |
} | |
static let tableView: UIViewStyle<UITableView> = UIViewStyle { tableView in | |
tableView.separatorStyle = .none | |
background.styling(tableView) | |
} | |
} | |
// Usage: | |
// BaseStyles.rounded().styling(view) | |
// BaseStyles.background.apply(to: view) | |
// BaseStyles.card.apply(to: view) | |
// BaseStyles.border(width: 0.5, color: .grey).styling(view) |
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
import Foundation | |
import UIKit | |
struct LabelStyle { | |
static func base(with size: CGFloat) -> UIViewStyle<UILabel> { | |
return UIViewStyle { label in | |
label.font = Font.regular(size) | |
} | |
} | |
static func baseBold(with size: CGFloat) -> UIViewStyle<UILabel> { | |
return UIViewStyle { label in | |
label.font = Font.bold(size) | |
} | |
} | |
static let big: UIViewStyle<UILabel> = base(with: 30) | |
static let bigBold: UIViewStyle<UILabel> = baseBold(with: 30) | |
static let base: UIViewStyle<UILabel> = LabelStyle.base(with: 18) | |
static let baseBold: UIViewStyle<UILabel> = LabelStyle.baseBold(with: 18) | |
static let small: UIViewStyle<UILabel> = base(with: 14) | |
static let smallBold: UIViewStyle<UILabel> = baseBold(with: 14) | |
static let blue: UIViewStyle<UILabel> = UIViewStyle { label in | |
label.textColor = UIColor.blue | |
} | |
static let darkGrey: UIViewStyle<UILabel> = UIViewStyle { label in | |
label.textColor = UIColor.darkGrey | |
} | |
static let grey: UIViewStyle<UILabel> = UIViewStyle { label in | |
label.textColor = UIColor.grey | |
} | |
static let black: UIViewStyle<UILabel> = UIViewStyle { label in | |
label.textColor = UIColor.black | |
} | |
static let white: UIViewStyle<UILabel> = UIViewStyle { label in | |
label.textColor = UIColor.white | |
} | |
static let dialogTitle: UIViewStyle<UILabel> = UIViewStyle { label in | |
LabelStyle.baseBold.styling(label) | |
LabelStyle.blue.styling(label) | |
} | |
static let dialogText: UIViewStyle<UILabel> = UIViewStyle { label in | |
LabelStyle.small.styling(label) | |
LabelStyle.black.styling(label) | |
} | |
} | |
// Usage: | |
// LabelStyle.smallBold.apply(to: label) | |
// LabelStyle.darkGrey.apply(to: label) |
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
import UIKit | |
import RxSwift | |
import RxCocoa | |
/// An abstraction if `UIView` styling. | |
struct UIViewStyle<T: UIResponder> { | |
/// The styling function that takes a `UIView` instance | |
/// and performs side-effects on it. | |
public let styling: (T) -> Void | |
/// A factory method that composes multiple styles. | |
/// | |
/// - Parameter styles: The styles to compose. | |
/// - Returns: A new `UIViewStyle` that will call the input styles' | |
/// `styling` method in succession. | |
static func compose(_ styles: UIViewStyle<T>...) -> UIViewStyle<T> { | |
return UIViewStyle { view in | |
for style in styles { | |
style.styling(view) | |
} | |
} | |
} | |
/// Compose this style with another. | |
/// | |
/// - Parameter other: Other style to compose this style with. | |
/// - Returns: A new `UIViewStyle` which will call this style's `styling`, | |
/// and then the `other` style's `styling`. | |
func composing(with other: UIViewStyle<T>) -> UIViewStyle<T> { | |
return UIViewStyle { view in | |
self.styling(view) | |
other.styling(view) | |
} | |
} | |
/// Compose this style with another styling function. | |
/// | |
/// - Parameter otherStyling: The function to compose this style with. | |
/// - Returns: A new `UIViewStyle` which will call this style's `styling`, | |
/// and then the input `styling`. | |
func composing(with otherStyling: @escaping (T) -> Void) -> UIViewStyle<T> { | |
return self.composing(with: UIViewStyle(styling: otherStyling)) | |
} | |
/// Apply this style to a UIView. | |
/// | |
/// - Parameter view: the view to style | |
func apply(to view: T) { | |
styling(view) | |
} | |
/// Apply this style to multiple views. | |
/// | |
/// - Parameter views: the views to style | |
func apply(to views: T...) { | |
for view in views { | |
styling(view) | |
} | |
} | |
} | |
extension Reactive where Base: UIResponder { | |
var style: Binder<UIViewStyle<UIResponder>> { | |
return Binder(self.base) { control, style in | |
style.apply(to: control) | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment