GitHub - yonaskolb/Stylist: Define UI styles in a hot-loadable external yaml or...
source link: https://github.com/yonaskolb/Stylist
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
README.md
Stylist ?
Stylist lets you define UI styles in a hot-reloadable external yaml or json theme file
- ✅ Define styles in external themes
- ✅ Apply styles through code or Interface Builder
- ✅Hotload themes to see results immediatly without recompiling
- ✅ Apply styles by style names or classes
- ✅ Styles can be applied to only certain view heirachies
- ✅Swap entire themes on the fly
- ✅ Built in style properties for all popular UIKit classes
- ✅ Reference Theme variables for commonly used values
- ✅ Use style inheritence
- ✅ Define custom strongly type properties and custom parsing to set any property you wish
- ✅ Make your own classes styleable
Example theme:
variables: primaryColor: "DB3B3B" headingFont: Ubuntu styles: UIButton: backgroundImage: buttonBack backgroundImage:highlighted: buttonBack-highlighted MyApp.Section: styles: [themed] axis(horizontal:regular): horizontal axis(horizontal:compact): vertical MyApp.Section UIStackView UILabel: styles: [content] primaryButton: textColor: "55F" textColor:highlighted: white contentEdgeInsets: [10,5] font(device:iphone): $headingFont:16 font(device:ipad): $headingFont:22 secondaryButton: backgroundColor: $primaryColor cornerRadius: 10 textColor: white font: 20 contentEdgeInsets: 6 sectionHeading: font: title 2 color: darkGray content: font: Arial:content color: "1D1D1D" themed: tintColor: $primaryColor
⬇️ Installing
Cocoapods
Add the following to your podfile
pod 'Stylist'
Carthage
Add the following to your Cartfile
github "yonaskolb/Stylist"
? Theme
A theme file has a list of variables
and a list of styles
.
Variables can be referenced in styles using $variableName
.
To load a Theme simply call:
Stylist.shared.load(path: pathToFile)
You can load multiple themes, and they will all be applied as long as they have different paths.
You can also load a Theme manually and then add it by name, allowing you to swap themes at runtime.
let theme = try Theme(path: pathToTheme) Stylist.shared.addTheme(theme, name: "mainTheme")
? Style
Styles are defined using one or more selectors. Selectors can be a class or a style or both. Custom classes must be prefixed by the module name. Styles must start with a lowercase.
UIButton
all UIButtonsMyApp.MyView
all MyView classes in the MyApp ModuleUITabBar.primary
all tab bars with the primary styleprimary
all views with the primary style
There can be multiple selectors seperated by a space, which then check if the later selectors are contained in the earlier selectors. This only applies to UIViews, and the containers don't have to be direct superviews but can be further up the chain.
For example, the following style will be applied to any UIButton
this is contained within a view with a section
style, that is then inside a UIStackView
with the main
style.
styles: UIStackView.main section UIButton: font: title3
Each style may also have a styles
array that is an array of other inherited styles, who's properties will also be applied.
Setting a Style
Class styles will be applied to UIViews when they are added to a superview.
To set a custom style on a UIView, simply set it's style
property:
myView.style = "myStyle"
You can also set a
styles
array that will apply multiple styles in order.
A style can also be set in Interface Builder in the identity inspector using runtime attributes.
? Style Properties
Many UIKit views and bar buttons have built in properties that you can set. These can be viewed in Style Properties.
? Hot Reloading
You can choose to watch a Theme files which means that whenever that file is changed the styles are reloaded. These changes can also be animated!
Themes can live at a remote url allowing you to even update styles remotely.
Hotloading can also be very useful while developing, as you can make changes to your styles on the fly without recompiling and see the results animate in instantly! To watch a file simply call watch
on stylist and pass in a URL to a local file on disk or a remote url:
Stylist.shared.watch(url: fileOrRemoteURL, animateChanges: true) { error in print("An error occured while loading or parsing the file: \(error)") }
If an error occurs at any time the parsingError
callback will be called with a ThemeError
, which will tell you exactly what went wrong including any formatting errors or invalid references. This means you can accidentally save an invalid theme without worrying that things will blow up.
To stop watching the file, you can call stop()
on the FileWatcher
that is returned.
Note that if a style property was present and you then remove it, Stylist cannot revert the change so that property will remain in the previous state.
⚙️ Custom Properties
Custom properties and parsers can also be added to let you configure anything you wish in a strongly typed way:
Stylist.shared.addProperty("textTransform") { (view: MyView, value: PropertyValue<MyProperty>) in view.myProperty = value.value }
addProperty
takes a style name a simply generic closure that sets your property on your view. This closure can contain any other logic you wish. The view can be NSObject and the property must conform to StyleValue
which is a simply protocol:
public protocol StyleValue { associatedtype ParsedType static func parse(value: Any) -> ParsedType? }
Many different types of properties are already supported and listed here in Style Property Types
The PropertyValue
that get's passed into the closure will have a value
property containing your parsed value. It also has a context
which contains property query values like device type, UIControlState and UIBarMetrics.
When a theme is loaded or when a style is set on a view, these custom properties will be applied if the view type and property name match.
⚙️ Custom Styleable class
By default UIView
and UIBarItem
are styleable. You can make any custom class styleable as well by conforming to the Styleable
protocol.
UIView
and UIBarItem
automatically call applyStyles
, so you will have to do that automatically in your styles
setter.
public protocol Styleable: class { var styles: [String] { get set } } extension Styleable { func applyStyles() { Stylist.shared.style(self) } }
? Attributions
This tool is powered by:
? Contributions
Pull requests and issues are welcome
? License
Stylist is licensed under the MIT license. See LICENSE for more info.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK