1. Home
  2. Developers
  3. iOS
  4. Interface Customization: iOS

Interface Customization: iOS

Our iOS SDK is 100% open source, and as such, you can modify the UI and underlying code at any time. However, the Apptentive iOS SDK is built in such a way that simple UI style changes are very easy to make without having to modify our code.

If you have a need for customizing the UI beyond what is covered below, we’d love to hear from you!

Customizing the User Interface

There are four main ways of customizing the Apptentive iOS UI, from least to most complex:

  1. Using tintColor and UIAppearance
  2. Using the Apptentive style sheet object
  3. Using a custom style object
  4. Forking the Apptentive iOS SDK

Using tintColor and UIAppearance

tintColor

By default, the Apptentive UI uses the tint color of your app’s main window. To customize the appearance of the tint color within the Apptentive UI only, you can set the tint color on UIView‘s UIAppearance proxy when contained in instances of ApptentiveNavigationController.

For iOS versions prior to 9.0, use the -appearanceWhenContainedIn: method in Objective-C:

[UIView appearanceWhenContainedIn:[ApptentiveNavigationController class], nil].tintColor = <#custom tint color#>;

For projects targeting iOS 9.0 and later, use the appearanceWhenContainedInInstancesOfClasses(_:) method (Swift projects targeting iOS versions prior to 9.0 will have to use the aforementioned Objective-C snippet):

UIView.appearanceWhenContainedInInstancesOfClasses([ApptentiveNavigationController.self]).tintColor = <#tint color#>

Note that the navigation bars used in the Apptentive UI will default to a white background color (technically a white barTintColor) if no further customizations are made. This can cause white status bar text and icons, as well as white navigation item titles and bar button items to be invisible. In this case you should make sure to set a contrasting bar tint or background color for the navigation bar as described above.

Global Appearance

You can use iOS’s built-in UIAppearance capabilities to customize a number of global color and font attributes. By default, the Apptentive UI will use these settings if they are set globally or when contained in instances of ApptentiveNavigationController (Note that if no appearance overrides are set, the navigation bar in the Apptentive UI will default to a white bar tint color).

For instance, you can customize your app’s navigation bar as follows, and the Apptentive UI will use these same values:

UINavigationBar.appearance().barTintColor = UIColor.redColor()
UINavigationBar.appearance().titleTextAttributes = [
    NSForegroundColorAttributeName: UIColor.whiteColor(),
    NSFontAttributeName: UIFont(name: "AmericanTypewriter-Bold", size: 17.0)!
]
UIBarButtonItem.appearance().tintColor = UIColor.whiteColor()
UIApplication.sharedApplication().statusBarStyle = .LightContent // Also set UIViewControllerBasedStatusBarAppearance to NO in Info.plist

This will set the navigation bar color to red, with a white title and buttons, and a typewriter-style font:

Customized Navigation Bar

If your app requires view controller-based status bar styles, you can extend ApptentiveNavigationController to specify .lightContent as its preferred status bar style:

extension ApptentiveNavigationController {
  open override var preferredStatusBarStyle: UIStatusBarStyle {
    get {
      return .lightContent
    }
  }
}

Using a Style Sheet Object

For non-global styles, using UIAppearance quickly becomes cumbersome or impossible (for instance, consider a standard UITableViewCell with two labels; there is no way to individually target those labels using UIAppearance). To supplement UIAppearance, we have added a style sheet object to the 3.0 release of the Apptentive iOS SDK.

The style sheet object is a read-write property of the Apptentive singleton that conforms to the ApptentiveStyle protocol. You can either use the ApptentiveStyleSheet object created when the singleton is initialized, or set your own object that conforms to the ApptentiveStyle protocol after initialization.

Using ApptentiveStyleSheet

The style sheet object provides a series of colors and fonts for use by various parts of the Apptentive UI. Many of the fonts are described by the UIFontTextStyle string constants, such as UIFontTextStyleBody. In addition, a number of text styles and colors have custom keys that you can find in the ApptentiveStyleSheet.h file. All font sizes respect the Dynamic Type settings for the device.

Below is an example of how you might create a “dark mode” theme, using a font other than the built-in system font:

UINavigationBar.appearance().barTintColor = UIColor.blackColor()
UINavigationBar.appearance().titleTextAttributes = [
    NSForegroundColorAttributeName: UIColor.whiteColor(),
    NSFontAttributeName: UIFont(name: "Avenir-Heavy", size: 17.0)!
]
UIBarButtonItem.appearance().tintColor = UIColor.whiteColor()
UIApplication.sharedApplication().statusBarStyle = .LightContent // Also set UIViewControllerBasedStatusBarAppearance to NO in Info.plist

if let style = Apptentive.sharedConnection().styleSheet as? ApptentiveStyleSheet {
    style.fontFamily = "Avenir"
    style.regularFaceAttribute = "Book"
    style.boldFaceAttribute = "Heavy"

    style.backgroundColor = UIColor.blackColor()
    style.primaryColor = UIColor.whiteColor()
    style.secondaryColor = UIColor(white: 0.8, alpha: 1.0)
    style.separatorColor = UIColor.grayColor()
    style.failureColor = UIColor(red: 1, green: 0.5, blue: 0.5, alpha: 1.0);
    style.collectionBackgroundColor = UIColor.darkGrayColor()
}

Dark Mode Theme

Fonts

To use a non-system font, set the ApptentiveStyleSheet‘s ‘fontFamily property to the name of the font you would like to use. You can use the iOS Fonts website to find the font family name for the fonts included with iOS (you’ll want to use the name in the heading above the list of typefaces in each font family).

Because the naming of various font weights is not standardized, you may have to customize the modifiers used for identifying each weight of your chosen font. You do this by setting the corresponding face attribute property. For example, the built-in Avenir font’s regular weight is called “Avenir-Book”, so the regular face attribute is set to “Book”. Some fonts omit the suffix entirely for their regular weight. In that case, set the face attribute to nil. Available attribute properties are lightFaceAttribute, regularFaceAttribute, mediumFaceAttribute, and boldFaceAttribute, which default to “Light”, “Regular”, “Medium” and “Bold”, respectively.

Some fonts may not include all four weights used by the style sheet object. In that case you may need to set one or more of them to use another weight.

Finally, you can globally adjust the font size used by the Apptentive UI by modifying the sizeAdjustment property, which acts as a global multiplier to the font sizes that would otherwise be used.

Colors

There are six colors that can be modified to change the appearance of the Apptentive UI:

  • primaryColor (defaults to UILabel‘s textColor appearance property)
  • secondaryColor (defaults to #8E8E93)
  • failureColor (defaults to #DA3547)
  • backgroundColor (defaults to UITableViewCell‘s backgroundColor appearance property)
  • separatorColor (defaults to UITableView‘s separatorColor appearance property)
  • collectionBackgroundColor (defaults to UITableView‘s backgroundColor appearance property)

The primary, secondary, and failure colors need to contrast well with the background color. The separator and collection background colors are mostly a matter of aesthetics. This survey shows an example of how theses colors are used:

Survey Colors

Initializing from a Property List

You can also create an instance of the ApptentiveStyleSheet class using values from a property list. Use the initWithContentsOfURL: initializer and set Apptentive.shared.styleSheet property to the result. The Apptentive Cordova integration for iOS does this for you.

The property list consists of a top-level dictionary with keys that are as follows:

  • FontFamily
  • LightFaceAttribute
  • RegularFaceAttribute
  • MediumFaceAttribute
  • BoldFaceAttribute
  • PrimaryColor
  • SecondaryColor
  • FailureColor
  • BackgroundColor
  • SeparatorColor
  • CollectionBackgroundColor
  • PlaceholderColor
  • SizeAdjustment
  • ColorOverrides
  • FontOverrides

All but the last three have string values. Color values should be specified as web color in the format of a pound sign followed by three two-digit hexadecimal numbers specifying red, green and blue (e.g. #FFFFFF for white).

The value for the SizeAdjustment key is a number specifying a global change to the size of the text in the Apptentive UI, where 1.0 is normal size. This is useful if a particular font family at the default size is too small or too large everywhere.

The ColorOverrides and FontOverrides override specific styles and should have dictionary values. The following keys work for both font and color sub-dictionaries:

  • com.apptentive.body
  • com.apptentive.header.title
  • com.apptentive.header.message
  • com.apptentive.message.date
  • com.apptentive.message.sender
  • com.apptentive.message.status
  • com.apptentive.messageCenter.status
  • com.apptentive.survey.question.instructions
  • com.apptentive.doneButton
  • com.apptentive.button
  • com.apptentive.submitButton
  • com.apptentive.textInput

The keys below are only used when specifying colors:

  • com.apptentive.color.header.background
  • com.apptentive.color.footer.background
  • com.apptentive.color.failure
  • com.apptentive.color.separator
  • com.apptentive.color.cellBackground
  • com.apptentive.color.collectionBackground
  • com.apptentive.color.textInputBackground
  • com.apptentive.color.textInputPlaceholder
  • com.apptentive.color.messageBackground
  • com.apptentive.color.replyBackground
  • com.apptentive.color.contextBackground
  • For color overrides, the values again are six-digit hex web colors with a preceding pound sign.

    For font overrides, the values are dictionaries. These sub-sub-dictionaries should have keys of font and size. The value for the fonte>font key is a string describing the specific typeface (both font and weight—see http://iosfonts.com for a list of those included by the operating system). The value for the size key is a number describing the desired size in points.

    Using Your Own Style Sheet Object

    To further customize the fonts and colors used by the Apptentive UI, you can subclass ApptentiveStyleSheet or create your own implementation from scratch that conforms to the ApptentiveStyle protocol. Your implementation will have to return appropriate fonts and colors based on the keys listed in the ApptentiveStyleSheet.h file.

    To use your custom style object, simply set the styleSheet property on the Apptentive singleton to an instance of your style sheet class before displaying Apptentive UI.

    class MyStyleSheet: ApptentiveStyle {
        func fontForStyle(textStyle: String) {
            // ...
        }
    
        func colorForStyle(style: String) {
            // ...
        }
    }
    
    // In your App Delegate's application(_:didFinishLaunchingWithOptions:)
    Apptentive.sharedConnection().styleSheet = MyStyleSheet()
    

    If you would like the Apptentive UI to use Dynamic Type, your style sheet class will have to adjust font sizes appropriately. For reference the elements that can be styled, with their corresponding style/textStyle keys are illustrated below:

    Message Center Styles 1

    Message Center Styles 2

    Survey Styles

    Forking the Apptentive iOS SDK

    In general, we recommend against forking the Apptentive iOS SDK, since it requires that changes to the main Apptentive repository be merged into the fork when the former is updated.

    We plan to migrate the Apptentive iOS SDK’s architecture to a Model-View-ViewModel system, which will allow forks of the SDK to customize the look and feel of the SDK without re-implementing the logic. The first component that adheres to this architecture is the Surveys component.

    As stated above, we encourage you to explore using the built-in capabilities for customization, and contacting us if you have questions or feature requests, before creating a fork and modifying it.

Updated on January 22, 2018

Was this article helpful?

Related Articles