SDK for iOS Developer's Guide

Map Customization

Whether you want to optimize your map for a certain display size, use case, branding, or highlight objects which are important to your users, HERE SDK map customization feature allows you to have a fine level of control of your map view rendering characteristics.

This section presents the components and concepts you need to create your own map look-and-feel.

Map Schemes

To customize the map, the first step is to obtain an NMACustomizableScheme object from the map view. With this object you can then get and set properties to modify the map. You can change color, width, length, and other properties of map objects such as buildings, land features, roads, and so on. If the scheme you are customizing is currently at the affected zoom level and it is active, then the changes to properties are visible.

A custom scheme you create will not be permanently saved but will live as long as the map view object is in memory.

The class hierarchy is as follows:
  1. NMAMapView
  2. NMACustomizableScheme
  3. NMACustomizableVariable

First you create or get a custom scheme from the map view, then get the respective property, NMACustomizableVariable, and finally modify its properties using its accessor methods.

Map Customization Example on GitHub

You can find an example that demonstrates this feature at (Obj-C) and (Swift).

Scheme Customization

Map customization starts by selecting one of the predefined schemes (such as NMANormalDayScheme and NMANormalNightScheme) to serve as a starting point. These predefined schemes are not customizable themselves but provide the initial values from which your custom scheme is derived. It is necessary to have the proper permission to access this base scheme as well as permission to customize.

Example of pre-defined schemes that we are already familiar with are (respectively, Normal Day, Normal Night):

Figure 1. Normal Day scheme
Figure 2. Normal Night scheme

Creating Your First Map Scheme Customization

In this example we will change the float property CountryBoundary_Width which causes the following rendering effect:

Figure 3. Normal Country Boundary
Figure 4. Adjusted Country Boundary

Let's learn how to implement this simple change. To begin, once you decided which scheme to base on, create an NMACustomizableScheme object with the map view method:

NMACustomizableScheme * customScheme;
customScheme = [self.mapView createCustomizableSchemeWithName:@"myCustomScheme" basedOnScheme: NMAMapSchemeNormalDay];

Once you created the customizable scheme, you can retrieve it again anytime with the following code as long as the map view object is not destroyed. Custom schemes are created and valid only for the specific Map View from which they were obtained.

NMACustomizableScheme * customScheme = [self.mapView.getCustomizableSchemeWithName:@"myCustomScheme"];

Before setting the attributes you define the zoom range for which the change shall take effect. For this purpose helper class NMAZoomRange is provided taking a minimum and maximum zoom level value:

NMAZoomRange * myZoomRange = [[NMAZoomRange alloc] initWithMinZoomLevel:0.0f and toZoomLevel:20.0f];

You are now ready to read and set values. In the following example we read and change NMASchemeCountryBoundaryWidth property:

// to read a primitive (float) property value: provide the property name and the zoom level
float returnValue = [customScheme floatForProperty:NMASchemeCountryBoundaryWidth forZoomLevel: 10.0f];

// to set a float property: provide the property name, new value, and the previously created zoom range (NMAZoomRange)
[customScheme setFloatProperty NMASchemeCountryBoundaryWidth withValue:10.0f forZoomRange: myZoomRange];

As seen above, for simple types such as Integer and Float an object is not necessary for modification. For types such as color the methods return an object for easier manipulation.

Finally, you can activate the custom scheme in the map:

[self.mapView setMapScheme:@"myCustomScheme"];
Note: It is perfectly fine to create a custom theme and activate it before making any customization changes. This way when changes are applied, they are immediately rendered and visible on the map view as the properties are modified with their respective setters.

You should now see the map as the following:

Figure 5. Adjusted Country Boundary

Listing the available customizable properties

All available properties can be found in NMACustomizableVariable.h header file. For each property type an NS_ENUM exists, which is passed as an identifier of the property to its get and set methods. You can refer to the header file to find out its type.

One set of accessor is available for each type of property, for example: integerForProperty:, floatForProperty:, and colorForProperty:. The same goes for setter methods.

Note: The class NMACustomizableVariable also has the static method allAvailableProperties which returns an NSDictionary with all the properties HERE SDK supports for customization (containing all NMACustomizableVariable objects, with its name as the key). This is especially useful if one wants to programmatically iterate through all the properties. It is always possible to find out the property type by reading propertyType from the NMACustomizableVariable object.
In the iOS SDK the following helper classes exist:
  • NMACustomizableVariable - Base class, used for primitive types such as integer and float
  • NMACustomizableColor - Extends NMACustomizableVariable with methods to handle color properties

Changing Color Properties

In the following example you can see how to modify NMASchemeBuildingColor property:

Figure 6. Normal Building Color
Figure 7. Adjusted Building Color

To modify color map attributes, we first obtain the custom color object NMACustomizableColor, then modify it:

NMACustomizableColor *buildingColor = [customScheme colorForProperty:NMASchemeBuildingColor forZoomLevel:2.0f];
[buildingColor setRed:100.0f];
[buildingColor setGreen:100.0f];
[buildingColor setBlue:133.0f];

// now apply the changes using the previously created zoom range
[customScheme setColorProperty:buildingColor forZoomRange:myZoomRange];