Themer enables you to switch between light, dark, and system default theme modes, gives you default themed classes of each view, and allows you to define all assets (color, border color, font, border width...) for them, as well as giving you the option to make your own custom themed views and their assets. Moves code from your view by defining their looks from one place and makes changes to styling easy.
Themer is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod 'Themer'
- switching between light / dark / system default
- animated theme changes
- listening to theme changes
- themed views, not just colors and fonts
- adding multiple custom themed views
Themer is straight forward to use, setup your themes and apply whatever theme you want!
Define your themes by inheriting from 'ApplicationTheme'. It enables you to define many different assets for your themed views in that theme.
class DarkTheme: ApplicationTheme {
var theme: Theme = Theme(
assets: ThemeAssets(
labelAssets: LabelAssets(
color: .orange,
font: .systemFont(ofSize: 48),
backgroundColor: .white
),
buttonAssets: ButtonAssets(
buttonColor: .black,
titleColor: .white,
font: .systemFont(ofSize: 28),
cornerRadius: 80,
borderColor: .systemPurple
),
imageViewAssets: ImageViewAssets(
tintColor: .systemRed
)))
}
class LightTheme: ApplicationTheme {
var theme: Theme = DarkTheme().theme.copyWith(ThemeAssets(
labelAssets: LabelAssets(
color: .blue
)))
In your app, as soon as possible, setup your theme. By default, when you first start your app, theme will be whatever the system default is.
Themer.shared.setup(lightTheme: LightTheme(), darkTheme: DarkTheme())
Anywhere in your application, you can apply a theme and your app theme will change. You can also use animations when applying a theme.
// Instant theme switch
Themer.shared.apply(.dark)
// Fancy theme switch
Themer.shared.apply(.systemDefault, withAnimation: ThemeAnimationSettings(duration: 0.4, delay: 0, animationOptions: .transitionFlipFromTop))
In your theme, all assets correspond to their themed versions. So, 'ButtonAssets' define what 'ThemedButton' looks like.
Instead
let button = UIButton()
Use
let button = ThemedButton()
'ThemedButton' is just like a normal UIButton, but all the properties from 'ButtonAssets' will be applied to it. So, you don't need any styling for it anywhere.
NavigationBarAssets are initialized differently than other assets. All three appearance's need to be accounted for: standard, compact and scroll edge. You are given a closure for each one, with a paramater being an instance of the 'UINavigationBarAppearance' that you can change properties on for each appearance, everything else is the same.
navigationBarAssets: NavigationBarAssets(standardApprance: { appearance in
appearance.backgroundColor = .blue
appearance.titleTextAttributes = [.font : UIFont.systemFont(ofSize: 28), .foregroundColor : UIColor.purple]
}, scrollEdgeApperance: { appearance in
appearance.titleTextAttributes = [.font : UIFont.systemFont(ofSize: 24), .foregroundColor : UIColor.yellow]
}, compactApperance: { appearance in
appearance.titleTextAttributes = [.font : UIFont.systemFont(ofSize: 20), .foregroundColor : UIColor.blue]
}
By default, standard appearance is applied on all appearances, whatever you do in scroll edge or compact appearance closures, will be added/changed based on the standard appearance. Note that on, for example, iOS 14 and 15, appearances behave a bit differently and you are free to check the current iOS version and set different values in each closure based on that. For example, I have found that in some situations scroll edge appearance is being applied on iOS 15, wherein iOS 14 standard appearance was applied.
Anywhere in your application, you can listen to theme changes using 'NotificationCenter'
let nc = NotificationCenter.default
nc.addObserver(self, selector: #selector(onThemeChanged), name: Themer.notificationName, object: nil)
Out of the box, you get a themed view like ThemedButton, ThemedNavigationBar, ThemedLabel... But, what if you want 2 or 3 different styles of buttons in a light and dark theme? No problem, just create a custom-themed view and attach assets to them.
class CustomThemedButton: ThemableButton {}
Themer.shared.addCustomAssets(to: .both, asset: ButtonAssets<CustomThemedButton>(buttonColor: .systemBrown))
let button = CustomThemedButton()
igniti0n, [email protected]
Themer is available under the MIT license. See the LICENSE file for more info.