Пользовательские шрифты

DivKit позволяет использовать пользовательские шрифты в вашем приложении. Это дает возможность сохранить единый стиль оформления текста на всех платформах и обеспечить соответствие дизайну вашего приложения.

Общая концепция

Для использования пользовательских шрифтов в DivKit необходимо:

  1. Добавить шрифты в ресурсы вашего приложения
  2. Реализовать провайдер шрифтов для соответствующей платформы
  3. Передать провайдер шрифтов в DivKit при инициализации
  4. Использовать имена шрифтов в JSON-разметке DivKit

В JSON-разметке DivKit шрифты указываются в параметре font_family элемента div-text:

Пример кода
{
  "type": "text",
  "font_family": "MyCustomFont",
  "font_weight": 500,
  "text": "Текст с пользовательским шрифтом"
}

Параметр font_weight определяет толщину шрифта и может принимать следующие значения:

  • 100 - Thin
  • 200 - Extra Light
  • 300 - Light
  • 400 - Regular (значение по умолчанию)
  • 500 - Medium
  • 600 - Semi Bold
  • 700 - Bold
  • 800 - Extra Bold
  • 900 - Black

Android

На платформе Android для использования пользовательских шрифтов необходимо реализовать интерфейс DivTypefaceProvider.

Пример реализации DivTypefaceProvider

import android.content.Context;
import android.graphics.Typeface;
import androidx.annotation.Nullable;
import com.yandex.div.core.font.DivTypefaceProvider;

public class CustomTypefaceProvider implements DivTypefaceProvider {
    private final Context context;

    // Кэшируем шрифты для повышения производительности
    private Typeface regularTypeface;
    private Typeface mediumTypeface;
    private Typeface lightTypeface;
    private Typeface boldTypeface;

    public CustomTypefaceProvider(Context context) {
        this.context = context;
    }

    @Nullable
    @Override
    public Typeface getRegular() {
        if (regularTypeface == null) {
            regularTypeface = Typeface.createFromAsset(context.getAssets(), "fonts/MyFont-Regular.ttf");
        }
        return regularTypeface;
    }

    @Nullable
    @Override
    public Typeface getMedium() {
        if (mediumTypeface == null) {
            mediumTypeface = Typeface.createFromAsset(context.getAssets(), "fonts/MyFont-Medium.ttf");
        }
        return mediumTypeface;
    }

    @Nullable
    @Override
    public Typeface getLight() {
        if (lightTypeface == null) {
            lightTypeface = Typeface.createFromAsset(context.getAssets(), "fonts/MyFont-Light.ttf");
        }
        return lightTypeface;
    }

    @Nullable
    @Override
    public Typeface getBold() {
        if (boldTypeface == null) {
            boldTypeface = Typeface.createFromAsset(context.getAssets(), "fonts/MyFont-Bold.ttf");
        }
        return boldTypeface;
    }

    // Опционально: переопределите метод getTypefaceFor для более точного контроля
    // над соответствием весов шрифтов
    @Nullable
    @Override
    public Typeface getTypefaceFor(int weight) {
        if (weight >= 0 && weight < 350) {
            return getLight();
        } else if (weight >= 350 && weight < 450) {
            return getRegular();
        } else if (weight >= 450 && weight < 650) {
            return getMedium();
        } else {
            return getBold();
        }
    }
}

Интеграция в приложение

import com.yandex.div.core.Div2Context;
import com.yandex.div.core.DivConfiguration;

// При инициализации DivKit
DivConfiguration configuration = new DivConfiguration.Builder()
    .typefaceProvider(new CustomTypefaceProvider(context))
    // другие настройки
    .build();

Div2Context div2Context = Div2Context.create(
    context,
    configuration
);

iOS

На платформе iOS для использования пользовательских шрифтов необходимо реализовать протокол DivFontProvider.

Добавление шрифтов в проект

  1. Добавьте файлы шрифтов (.ttf или .otf) в ваш проект
  2. Убедитесь, что шрифты включены в ресурсы приложения (Bundle Resources)
  3. Добавьте информацию о шрифтах в Info.plist в раздел Fonts provided by application:
<key>UIAppFonts</key>
<array>
    <string>MyFont-Regular.ttf</string>
    <string>MyFont-Medium.ttf</string>
    <string>MyFont-Light.ttf</string>
    <string>MyFont-Bold.ttf</string>
</array>

Пример реализации DivFontProvider

import UIKit
import DivKit
import VGSL

class CustomFontProvider: DivFontProvider {
    func font(family: String, weight: DivFontWeight, size: CGFloat) -> Font {
        // Если указано конкретное семейство шрифтов
        if family == "MyCustomFont" {
            let fontName: String
            switch weight {
            case .light:
                fontName = "MyFont-Light"
            case .regular:
                fontName = "MyFont-Regular"
            case .medium:
                fontName = "MyFont-Medium"
            case .bold:
                fontName = "MyFont-Bold"
            }

            if let font = UIFont(name: fontName, size: size) {
                return Font(uiFont: font)
            }
        }

        // Возвращаем системный шрифт, если пользовательский не найден
        let uiFont: UIFont
        switch weight {
        case .light:
            uiFont = UIFont.systemFont(ofSize: size, weight: .light)
        case .regular:
            uiFont = UIFont.systemFont(ofSize: size, weight: .regular)
        case .medium:
            uiFont = UIFont.systemFont(ofSize: size, weight: .medium)
        case .bold:
            uiFont = UIFont.systemFont(ofSize: size, weight: .bold)
        }

        return Font(uiFont: uiFont)
    }

    // Метод для получения шрифта по числовому весу уже реализован в расширении протокола
}

Интеграция в приложение

import DivKit

// При инициализации DivKit
let components = DivKitComponents(
    divCustomBlockFactory: nil,
    fontProvider: CustomFontProvider(),
    // другие параметры
)

Web

На платформе Web для использования пользовательских шрифтов необходимо:

  1. Подключить шрифты стандартными способами CSS (через @font-face или внешние сервисы)
  2. Использовать параметр typefaceProvider при инициализации DivKit

Подключение шрифтов через CSS

Имя шрифта в CSS не обязательно должно совпадать с именем в JSON.

Не забудьте предоставить все варианты начертаний и насыщенности, которые понадобятся в вашей разметке (в данном примере добравлены 400, 500 и 700). Ещё один вариант - использовать вариативные шрифты.

@font-face {
  font-family: 'MyCustomFont';
  src: url('fonts/MyFont-Regular.woff2') format('woff2'),
       url('fonts/MyFont-Regular.woff') format('woff');
  font-weight: 400;
  font-style: normal;
}

@font-face {
  font-family: 'MyCustomFont';
  src: url('fonts/MyFont-Medium.woff2') format('woff2'),
       url('fonts/MyFont-Medium.woff') format('woff');
  font-weight: 500;
  font-style: normal;
}

@font-face {
  font-family: 'MyCustomFont';
  src: url('fonts/MyFont-Bold.woff2') format('woff2'),
       url('fonts/MyFont-Bold.woff') format('woff');
  font-weight: 700;
  font-style: normal;
}

Использование typefaceProvider

import { render } from '@divkitframework/divkit/client';

render({
    id: 'my-divkit-container',
    target: document.querySelector('#root'),
    json: {
        card: {
            log_id: 'custom_fonts_example',
            states: [{
                state_id: 0,
                div: {
                    type: 'text',
                    font_family: 'MyCustomFont',
                    font_weight: 500,
                    text: 'Текст с пользовательским шрифтом'
                }
            }]
        }
    },
    typefaceProvider: (fontFamily, opts) => {
        // Можно реализовать сопоставление имен шрифтов из JSON с CSS
        if (fontFamily === 'MyCustomFont') {
            return 'MyCustomFont, sans-serif';
        }

        // Для варианта по умолчанию можно вернуть пустую строку
        return '';
    }
});

Примеры использования в JSON

Базовый пример

Пример кода
{
  "type": "text",
  "font_family": "MyCustomFont",
  "font_weight": 400,
  "text": "Текст с пользовательским шрифтом"
}

Разные стили шрифта

Пример кода
{
  "type": "container",
  "items": [
    {
      "type": "text",
      "font_family": "MyCustomFont",
      "font_weight": 300,
      "text": "Текст с легким шрифтом (Light)"
    },
    {
      "type": "text",
      "font_family": "MyCustomFont",
      "font_weight": 400,
      "text": "Текст с обычным шрифтом (Regular)"
    },
    {
      "type": "text",
      "font_family": "MyCustomFont",
      "font_weight": 500,
      "text": "Текст со средним шрифтом (Medium)"
    },
    {
      "type": "text",
      "font_family": "MyCustomFont",
      "font_weight": 700,
      "text": "Текст с жирным шрифтом (Bold)"
    }
  ]
}

Использование в шаблонах

Пример кода
{
  "templates": {
    "title": {
      "type": "text",
      "font_family": "MyCustomFont",
      "font_weight": 700,
      "font_size": 20,
      "$text": "title"
    },
    "body": {
      "type": "text",
      "font_family": "MyCustomFont",
      "font_weight": 400,
      "font_size": 16,
      "$text": "text"
    }
  },
  "card": {
    "log_id": "custom_fonts_example",
    "states": [
      {
        "state_id": 0,
        "div": {
          "type": "container",
          "items": [
            {
              "type": "title",
              "text": "Заголовок с пользовательским шрифтом"
            },
            {
              "type": "body",
              "text": "Основной текст с пользовательским шрифтом"
            }
          ]
        }
      }
    ]
  }
}

Узнать больше

Следите за новостями DivKit в Telegram-канале: http://t.me/divkit_news.

Также вы можете обсуждать интересующие вас темы в сообществе пользователей DivKit в Telegram: https://t.me/divkit_community_ru.

Репозиторий DivKit