iOS Preference Center Customization

Custom iOS Preference Center guide.

Installation

Preference Center requires adding the AirshipPreferenceCenter module:

For CocoaPods, import using:

import AirshipKit
@import AirshipKit;

For everything else use:

import AirshipPreferenceCenter
@import AirshipPreferenceCenter;

Styling the Preference Center

The preference center’s look can be customized by creating a PreferenceCenterTheme instance, setting its Theme properties, and then setting the Theme property of the Preference Center instance to the customized Theme instance.

For instance, we may want to change the color of the navigation bar in order to match our app and set custom fonts and colors for the different elements in the Preference Center.

Setting a Preference Center Theme

// Customize your Theme
var theme = PreferenceCenterTheme()
theme.viewController = PreferenceCenterTheme.ViewController(
    navigationBar: PreferenceCenterTheme.NavigationBar(
        title: "My preference center",
        backgroundColor: .orange
    )
)

theme.preferenceCenter = PreferenceCenterTheme.PreferenceCenter(
    subtitleAppearance: PreferenceCenterTheme.TextAppearance(
        font: .subheadline,
        color: .yellow
    ),
    retryButtonBackgroundColor: .green,
    retryButtonLabelAppearance: PreferenceCenterTheme.TextAppearance(
        font: .title3,
        color: .black
    )
)
theme.contactSubscription = PreferenceCenterTheme.ContactSubscription(
    titleAppearance: PreferenceCenterTheme.TextAppearance(
        font: .title,
        color: .red
    ),
    subtitleAppearance: PreferenceCenterTheme.TextAppearance(
        font: .title2,
        color: .yellow
    )
)

theme.channelSubscription = PreferenceCenterTheme.ChannelSubscription(
    titleAppearance: PreferenceCenterTheme.TextAppearance(
        font: .title,
        color: .red
    ),
    subtitleAppearance: PreferenceCenterTheme.TextAppearance(
        font: .title2,
        color: .yellow
    )
)

// Set the Theme on the default Preference Center UI
PreferenceCenter.shared.theme = theme

The theme can also be set in SwiftUI.

Setting a Preference Center Theme in SwiftUI

PreferenceCenterView(
    preferenceCenterID: "preferenceCenter-ID"
)
.preferenceCenterTheme(theme)

Customizing your Theme can also be done without writing code by creating a plist file. Create a plist with the desired preference center theme. All the keys correspond to properties on the PreferenceCenterTheme class.

Colors are represented by strings, either a valid color hexadecimal or a named color. Named color strings must correspond to a named color defined in a color asset within the main bundle.

Save the plist as AirshipPreferenceCenterTheme.plist file.

PreferenceCenterTheme being a struct, if your app is written in Objective-C you will have to use the plist file in order to customize your theme.

Styling the Preference Center using a plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>viewController</key>
        <dict>
            <key>navigationBar</key>
            <dict>       
                <key>title</key>
                <string>Preference Center</string>
                <key>titleFont</key>
                <dict>
                    <key>fontName</key>
                    <string>Helvetica</string>
                    <key>fontSize</key>
                    <string>15</string>
                </dict>
                <key>titleColor</key>
                <string>#0000FF</string>
            </dict>
        </dict>
        <key>preferenceCenter</key>
        <dict>
            <key>subtitleAppearance</key>
            <dict>
            </dict>
        </dict>
        <key>commonSection</key>
        <dict>
            <key>titleAppearance</key>
            <dict>
                <key>color</key>
                <string>#de0000</string>
                <key>font</key>
                <dict>
                    <key>fontName</key>
                    <string>Helvetica</string>
                    <key>fontSize</key>
                    <string>32</string>
                </dict>
            </dict>
            <key>subtitleAppearance</key>
            <dict>
                <key>color</key>
                <string>#da833b</string>
                <key>font</key>
                <dict>
                    <key>fontName</key>
                    <string>Helvetica</string>
                    <key>fontSize</key>
                    <string>25</string>
                </dict>
            </dict>
        </dict>
        <key>labeledSectionBreak</key>
        <dict>
            <key>titleAppearance</key>
            <dict>
            </dict>
        </dict>
        <key>channelSubscription</key>
        <dict>
            <key>titleAppearance</key>
            <dict>
                <key>color</key>
                <string>#034710</string>
                <key>font</key>
                <dict>
                    <key>fontName</key>
                    <string>Helvetica</string>
                    <key>fontSize</key>
                    <string>20</string>
                </dict>
            </dict>
            <key>subtitleAppearance</key>
            <dict>
                <key>color</key>
                <string>#8fe388</string>
                <key>font</key>
                <dict>
                    <key>fontName</key>
                    <string>Helvetica</string>
                    <key>fontSize</key>
                    <string>15</string>
                </dict>
            </dict>
        </dict>
        <key>contactSubscription</key>
        <dict>
            <key>titleAppearance</key>
            <dict>
                <key>color</key>
                <string>#034710</string>
                <key>font</key>
                <dict>
                    <key>fontName</key>
                    <string>Helvetica</string>
                    <key>fontSize</key>
                    <string>20</string>
                </dict>
            </dict>
            <key>subtitleAppearance</key>
            <dict>
                <key>color</key>
                <string>#8fe388</string>
                <key>font</key>
                <dict>
                    <key>fontName</key>
                    <string>Helvetica</string>
                    <key>fontSize</key>
                    <string>15</string>
                </dict>
            </dict>
        </dict>
        <key>contactSubscriptionGroup</key>
        <dict>
            <key>titleAppearance</key>
            <dict>
                <key>color</key>
                <string>#034710</string>
                <key>font</key>
                <dict>
                    <key>fontName</key>
                    <string>Helvetica</string>
                    <key>fontSize</key>
                    <string>20</string>
                </dict>
            </dict>
            <key>subtitleAppearance</key>
            <dict>
                <key>color</key>
                <string>#8fe388</string>
                <key>font</key>
                <dict>
                    <key>fontName</key>
                    <string>Helvetica</string>
                    <key>fontSize</key>
                    <string>15</string>
                </dict>
            </dict>
            <key>chip</key>
            <dict>
                <key>checkColor</key>
                <string>#3bd2d6</string>
                <key>borderColor</key>
                <string>#0a0fc9</string>
                <key>labelAppearance</key>
                <dict>
                    <key>color</key>
                    <string>#7c6bea</string>
                    <key>font</key>
                    <dict>
                        <key>fontName</key>
                        <string>Helvetica</string>
                        <key>fontSize</key>
                        <string>15</string>
                    </dict>
                </dict>
            </dict>
        </dict>
        <key>alert</key>
        <dict>
            <key>titleAppearance</key>
            <dict>
                <key>color</key>
                <string>#0a0fc9</string>
                <key>font</key>
                <dict>
                    <key>fontName</key>
                    <string>Helvetica</string>
                    <key>fontSize</key>
                    <string>15</string>
                </dict>
            </dict>
            <key>subtitleAppearance</key>
            <dict>
                <key>color</key>
                <string>#d1b4d4</string>
            </dict>
            <key>buttonLabelAppearance</key>
            <dict>
                <key>color</key>
                <string>#78c8c0</string>
                <key>font</key>
                <dict>
                    <key>fontName</key>
                    <string>Helvetica</string>
                    <key>fontSize</key>
                    <string>25</string>
                </dict>
            </dict>
            <key>buttonBackgroundColor</key>
            <string>#da833b</string>
        </dict>
    </dict>
</plist>
Customizing the Preference Center navigation stack

To customize the Preference Center’s parent navigation stack in SwiftUI, set its built-in navigation stack to type .none, wrap it in a NavigationStack, and directly apply your preferred configuration, such as display modes, styles, or toolbar items. Here’s an example of how to achieve this:

NavigationStack {
    PreferenceCenterView()
        .messageCenterNavigationStack(.none) // Disables default navigation stack
        .navigationTitle("Custom Message Center Title")
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItem(placement: .navigationBarTrailing) {
                Button("Settings") {
                    // Custom action for the toolbar button
                }
            }
        }
}

Embedding the Preference Center

When embedding the Preference Center you must specify the ID of the Preference center to be displayed.

SwiftUI

Embedding Preference Center in SwiftUI

PreferenceCenterView(preferenceCenterID: "preferenceCenter-ID")

UIKit

Embedding Preference Center in UIKit

// Make the view preference center view controller.
let preferenceCenterviewController = PreferenceCenterViewControllerFactory.makeViewController(preferenceCenterID: "preferenceCenter-ID")

// Add the view controller to the destination view controller.
if let preferenceCenterView = preferenceCenterviewController.view {
    addChild(preferenceCenterviewController)
    view.addSubview(preferenceCenterView)

    // Create and activate constraints.
    preferenceCenterView.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        preferenceCenterView.topAnchor.constraint(equalTo: view.topAnchor),
        preferenceCenterView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
        preferenceCenterView.leftAnchor.constraint(equalTo: view.leftAnchor),
        preferenceCenterView.rightAnchor.constraint(equalTo: view.rightAnchor),
    ])
}
UIViewController *preferenceCenterviewController = [UAPreferenceCenterViewControllerFactory makeViewControllerWithPreferenceCenterID:@"preferenceCenter-ID" dismissAction:nil];

// Add the view controller to the destination view controller.
UIView *preferenceCenterView = preferenceCenterviewController.view;
[self addChildViewController:preferenceCenterviewController];
[self.view addSubview:preferenceCenterView];

// Create and activate constraints.
preferenceCenterView.translatesAutoresizingMaskIntoConstraints = false;
[NSLayoutConstraint activateConstraints:@[
    [preferenceCenterView.topAnchor constraintEqualToAnchor:self.view.topAnchor],
    [preferenceCenterView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor],
    [preferenceCenterView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor],
    [preferenceCenterView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor]
]];