Home Creating Visual Cohesion in SwiftUI Apps. A Step-by-Step Guide to Themes
Post
Cancel

Creating Visual Cohesion in SwiftUI Apps. A Step-by-Step Guide to Themes

The Need For Visual Cohesion

In SwiftUI, theming your app can be a powerful way to create a consistent and visually appealing user interface. By defining a set of colors that represent your app’s design language, you can easily apply a visually cohesive set of colors throughout your app and make updates in one central location. In this article, we will explore a neat little way to set up themes in a SwiftUI app.

Stop Talking Show Me The Code

1
2
3
4
5
6
7
8
9
10
11
12
extension Color {
    static let theme = ColorTheme()
}


struct ColorTheme {
    let accent = Color("AccentColor")
    let background = Color("BackgroundColor")
    let green = Color("GreenColor")
    let primaryText = Color("primaryTextColor")
    let secondaryText = Color("SecondaryTextColor")
}

To accomplish an app wide reusable color theme, we will need a ColorTheme struct that contains various color properties such as accent, background, primaryText and secondaryText etc. These properties are of type Color and are initialized with colors defined by their corresponding color names, such as “AccentColor”, “BackgroundColor”, etc. These color names are expected to be defined in your app’s asset catalog or color asset file.

To make these colors accessible throughout our SwiftUI app, an extension is defined on the Color type, creating a static computed property called theme that returns an instance of the ColorTheme struct. This allows you to access the colors defined in your ColorTheme struct using the Color.theme syntax. You will see the beauty of this later on.

The code above is pretty intuitive but if you want a more descriptive explanation of what’s going on here’s a step-by-step guide:

  • Step 1: Define Your Color Theme

Start by defining your color theme in the ColorTheme struct. You can customize the color properties in the ColorTheme struct to match your app’s design language. For example, you can define the accent color, background color, and other color properties based on your app’s visual requirements.

  • Step 2: Define Color Assets

Next, define the actual colors in your app’s asset catalog or color asset file. You can define colors using the color picker in Xcode or by specifying the RGB or HSL values. Give each color a unique name that corresponds to the color names used in your ColorTheme struct. For example, if you have defined accent as a color property in your ColorTheme struct, you should define a color asset with the name “AccentColor” in your asset catalog or color asset file.

  • Step 3: Create the Color Extension

Once you have defined your color theme and color assets, you can create the Color extension to make your theme accessible throughout your app.

  • Step 4: Applying the Theme

Now you can easily apply the colors from your theme throughout your SwiftUI app using the Color.theme syntax. For example, you can set the accent color of a Text view like this:

1
2
Text("Hello, SwiftUI!")
    .foregroundColor(Color.theme.accent)

You can also use the other color properties defined in your ColorTheme struct to set colors for other SwiftUI views, such as backgrounds, buttons, and more.

  • Step 5: Update the Theme

One of the great advantages of theming is that you can easily update the colors in one central location. If you decide to change the accent color of your app, for example, you can simply update the accent property in your ColorTheme struct, and the changes will be automatically applied to all the views that use Color.theme.accent throughout your app.

Font Themes

You can use a similar approach for fonts in SwiftUI as well. Just like how you can define a ColorTheme struct to encapsulate your app’s color palette, you can create a FontTheme struct to encapsulate your app’s font styles. Here’s an example:

1
2
3
4
5
6
7
8
9
10
11
12
import SwiftUI

extension Font {
    static let theme = FontTheme()
}

struct FontTheme {
    let title = Font.custom("Avenir-Heavy", size: 24)
    let subtitle = Font.custom("Avenir-Medium", size: 18)
    let body = Font.custom("Avenir-Light", size: 16)
}

In this example, a FontTheme struct is defined with properties for different font styles such as title, subtitle, and body, each initialized with a custom font name and size. You can customize these font properties based on your app’s typography requirements.

Then, similar to the Color extension approach, you can create an extension on Font to provide easy access to the font styles defined in your FontTheme struct using the Font.theme syntax. For example, you can use Font.theme.title to set the title font style for a Text view.

1
2
Text("Hello, SwiftUI!")
    .font(Font.theme.title) 

This approach allows you to centralize and easily update font styles throughout your app, just like how theming with colors provides consistency and coherence to your app’s user interface.

I really like this approach and as you can imagine, we can apply this method beyond just colors and fonts. We can deploy this approach for ImageThemes, IconThemes, SpacingThemes, AnimationThemes etc. The world is your oyster with this approach.

This post is licensed under CC BY 4.0 by the author.