FAQ

Light and dark theme

There are several approaches when working with different themes.

  1. The app's color palette is set on the client.

    Create your variable storage DivVariableStorage and pass it to DivKitComponents.

    let applicationStorage = DivVariableStorage()
    let themeVariable: DivVariables = [
      DivVariableName(rawValue: "palette"): .dict([
        "text_color": "#ffffff",
        "text_background": "#0077FF"
      ])
    ]
    applicationStorage.put(themeVariable)
    let variablesStorage = DivVariablesStorage(outerStorage: applicationStorage)
    let divkitComponents = DivKitComponents(variablesStorage: variablesStorage)
    

    The layout itself will look like this:

    {
      "card": {
        "log_id": "text",
        "states": [
          {
            "state_id": 0,
            "div": {
              "type": "text",
              "text": "Hello, DivKit!",
              "height": {
                "type": "fixed",
                "value": 48
              },
              "border": {
                "corner_radius": 16
              },
              "background": [
                {
                  "type": "solid",
                  "color": "@{getColorFromDict(palette, 'text_background')}"
                }
              ],
              "margins": {
                "top": 20,
                "left": 20,
                "right": 20
              },
              "font_size": 14,
              "text_alignment_vertical": "center",
              "text_alignment_horizontal": "center",
              "text_color": "@{getColorFromDict(palette, 'text_color')}"
            }
          }
        ]
      }
    }
    

    Please note that that the JSON layout doesn't know anything about the palette variable, and you need to pass it from the client.
    To avoid errors, add a default value via the getOptColorFromDict function.

  2. The color palette is set on the server side.

    In this case, you need to know which theme is used in the app. To do this, create the global app_theme variable:

    let applicationStorage = DivVariableStorage()
    let themeVariable: DivVariables = [
      DivVariableName(rawValue: "app_theme"): .string("dark")
    ]
    applicationStorage.put(themeVariable)
    let variablesStorage = DivVariablesStorage(outerStorage: applicationStorage)
    let divkitComponents = DivKitComponents(variablesStorage: variablesStorage)
    

    The layout itself will look like this:

    {
      "card": {
        "variables": [
          {
            "name": "palette",
            "type": "dict",
            "value": {
              "light": {
                "text_color": "#ffffff",
                "text_background": "#0077FF"
              },
              "dark": {
                "text_color": "#000000",
                "text_background": "#0077FF"
              }
            }
          }
        ],
        "log_id": "text",
        "states": [
          {
            "state_id": 0,
            "div": {
              "type": "text",
              "text": "Hello, DivKit!",
              "height": {
                "type": "fixed",
                "value": 48
              },
              "border": {
                "corner_radius": 16
              },
              "background": [
                {
                  "type": "solid",
                  "color": "@{getColorFromDict(palette, app_theme, 'text_background')}"
                }
              ],
              "margins": {
                "top": 20,
                "left": 20,
                "right": 20
              },
              "font_size": 14,
              "text_alignment_vertical": "center",
              "text_alignment_horizontal": "center",
              "text_color": "@{getColorFromDict(palette, app_theme, 'text_color')}"
            }
          }
        ]
      }
    }
    

Troubleshooting in DivKit

To simplify layout debugging on the client, DivKit has an indicator for layout errors. By default, this indicator is disabled. To enable it, additionally pass DebugParams:

divView.setSource(DivViewSource(kind: .data(jsonData), 
                                cardId: "ExampleCard"),
                  debugParams: DebugParams(isDebugInfoEnabled: true))

For example, let's pass an invalid value to corner_radius:

"border": {
    "corner_radius": "incorrect_value"
},

An error indicator appears in the layout:

Interacting with it shows you errors in the debug panel.

To log errors, pass the reporter parameter to DivKitComponents.

Non-functional visibility_actions

Let's consider a layout where a visibility_action is called after 1 second, and the button text changes.

{
  "card": {
    "variables": [
        {
            "name": "button_text",
            "type": "string",
            "value": "Waiting visibility action"
        }
    ],
    "log_id": "text",
    "states": [
      {
        "state_id": 0,
        "div": {
          "type": "text",
          "text": "@{button_text}",
          "height": {
            "type": "fixed",
            "value": 48
          },
          "border": {
            "corner_radius": 16
          },
          "background": [
            {
              "type": "solid",
              "color": "#0077FF"
            }
          ],
          "margins": {
            "top": 20,
            "left": 20,
            "right": 20
          },
          "font_size": 14,
          "text_alignment_vertical": "center",
          "text_alignment_horizontal": "center",
          "visibility_actions": [
            {
                "log_id": "example",
                "visibility_duration": 1000,
                "url": "div-action://set_variable?name=button_text&value=Visibility%20action%20called!"
            }
          ]
        }
      }
    ]
  }
}

If nothing is done on the client side, this action won't be called. DivView doesn't know how visible it is on the screen. When DivView becomes visible on the screen, you need to call the onVisibleBoundsChanged method:

divView.onVisibleBoundsChanged(to: visibleSize)

Does DivKit support the Right-To-Left interface?

Yes. You need to pass the layoutDirection parameter to DivKitComponents, and RTL elements will be displayed correctly.

let divkitComponents = DivKitComponents(layoutDirection: .rightToLeft)

Can I use local pictures when working with DivView?

By default, DivKit can load pictures from divkit to the app's main bundle as URLs in the following format: divkit-asset://image.png.

You can also write a custom image selection logic. To do this, create your ImageHolderFactory that can turn a URL into a path to an image in the file system.

let imageHolderFactory = ImageHolderFactory(localImageProvider: self, requestPerformer: URLRequestPerformer(urlTransform: nil))
let divkitComponents = DivKitComponents(imageHolderFactory: imageHolderFactory)

extension ViewController: LocalImageProviding {
  func localImage(for url: URL) -> BasePublic.ImageHolder? {
    guard url.scheme == "localImage" else { return nil }
    return UIImage(named: url.host()!)
  }
}

The JSON itself will look like this:

{
  "card": {
    "log_id": "image",
    "states": [
      {
        "state_id": 0,
        "div": {
          "type": "container",
          "items": [
            {
              "type": "image",
              "image_url": "localImage://image",
              "height": {
                "type": "match_parent"
              }
            }
          ],
          "width": {
            "type": "match_parent"
          },
          "height": {
            "type": "fixed",
            "value": 100
          },
          "margins": {
            "top": 8,
            "bottom": 8,
            "left": 8,
            "right": 8
          }
        }
      }
    ]
  }
}

Learn more

Follow DivKit news in the Telegram channel: http://t.me/divkit_news

You can also discuss topics of interest in the DivKit user community in Telegram: https://t.me/divkit_community_ru

DivKit Repository