Theming

Throughout Redbeard a powerful theming engine is at work styling and configuring user interface components. This way, style information is abstracted away from the code, keeping the code minimal and clean. Additionally, the theme information is then able to be expressed in a way that is superior and more fitting it’s nature.

Expressive

The theming engine uses a 'CSS'-like theming approach using 'JSON' syntax. Each component accepts a wide variety of theming options, including the following:

  • Numeric values, such as measurements
  • Colors
  • Enumeration Values
  • Images and glyphs such as font-awesome
  • Spacing and Margins
  • Strings such as titles, including localisation.
  • Borders
  • Shadows
  • Corner Rounding
  • Visibility
  • Much more.

Additionally, components can be given themes that are specific to particular states - such as a button when selected or a form field when it’s value has failed validation. For example, below you can see the way a cell looks when in it’s normal state and it's highlighted state respectively. Each of these states are separately themed, where the theme specifies how the colors change from normal to highlighted.

Constants

The theming engine supports constants that can then be referred to as a way of specifying in one place some theming information that is used in multiple locations - they can also cross-reference each other.

This way, it is possible to override the value of the constants that are defined in a theme that you are using. Redbeard ships with two default themes, here is an example of overriding a constant value to change a fundamental attribute of the theme:

Create a new file, in this case named "colors.const.json":

                    {
     "color-primary": "ref://palette-yellow-500",
     "color-primary-dark": "ref://palette-yellow-700",
     "color-primary-light": "ref://palette-yellow-100",
     "color-accent": "ref://palette-deep-orange-500",
     "color-accent-dark": "ref://palette-deep-orange-700",
     "color-accent-light": "ref://palette-deep-orange-100"
}
                        
Include this file in the `theme.inc.json` file:
                    "constants":
[
     "colors.const.json"
],

                        
Before and after:

Inheritance

The inheritance tree of components is taken into account, meaning that the theming options are processed down the class inheritance hierarchy. This way, when you subclass a view or view controller the theming behaviour of the superclass is respected. You can then override this behaviour and add your own theming options.

Hierarchy

Views and view controllers tend to manage their own subviews and child view controllers. Therefore, a theme for a component often includes sub-themes for it’s managed subviews and child view controllers. It is easy for a view or view controller when it is processing a theme update to pass on the relevant theming information to it’s children. This way, a hierarchy is possible to provide fine-grained theming options to a complex component.

Out of the Box

All Redbeard controls are theme-able out of the box. Additionally, a number of native cocoa controls have also been provided with out-of-the-box theming support, allowing you to theme them with Redbeard immediately - even in existing projects. This also applies to any subclasses, including your own. The main native cocoa components that have out-of-the-box theming are:

  • UIView
  • UILabel
  • UIButton
  • UIViewController

Easy to use in your own components

When you subclass any `UIView` or 'UIViewController' class, you benefit from inheriting it’s theming functionality. It is also easy and convenient to add your own theming both for the subclass itself, and for any views or view controllers that it manages - you simply have to implement `applyTheme:` and remember to call super.

In 'applyTheme:', you do a combination of: Pass theme information on to your child views and view controllers - providing hierarchy. Assign theme values to your local properties.

Here is an example of an 'applyTheme:' implementation for a component - in this case the 'RBRatingView' component:

                    - (void)applyTheme:(NSDictionary *)theme
{
    [super applyTheme:theme];

    RB_THEME_SET_ENUM(theme, @"RBOrientation", self.orientation, @"orientation");
    RB_THEME_SET(theme, unsignedIntegerFromTheme, self.maximumRating, @"maximumRating");
    RB_THEME_SET(theme, floatFromTheme, self.rating, @"rating");
    RB_THEME_SET(theme, imageFromTheme, self.unfilledImage, @"unfilledImage");
    RB_THEME_SET(theme, imageFromTheme, self.filledImage, @"filledImage");

    [self.layoutView.theme pushChanges:theme];
    [self.layoutView.theme processChanges];
}  

The 'RB_THEME_SET' and 'RB_THEME_SET_ENUM' macros make reading a theme value into a property easy and convenient, no matter what type the property is. It ensures that this is done safely and efficiently.

On all `UIView` and 'UIViewController' instances, there is a 'theme' property that can be used to push theming changes and commit them. In the example above, we’re passing the theme information on to the child layout view.

That is all the code required to add full theming support to the component.

Icons

For convenience, the theming engine in Redbeard also provides functionality for glyphs, with font-awesome provided out-of-the-box. It is easy using the relevant notation to specify a glyph with any color or size desired.

Here is an example using the `RBRatingView` mentioned above. Here we will use the glyph notation to determine what the “star” images should be, including their color:

“unfilledImage”: "glyph://star-small/#777777”,
                    “filledImage”: "glyph://star-small/#FD990E”
“unfilledImage”: "glyph://apple-small/#777777”,
                    “filledImage”: "glyph://apple-small/#FD990E"

Click Here to read more about this notation and which glyphs are provided. It is also possible to add your own glyphs and benefit from this functionality.

Reference Documentation

For more information about the theming options that are available, visit the theme reference documentation here.