Темы
Обзор уровней кастомизации, ключевых понятий и архитектуры — на странице Дизайн-система: введение.
Эта страница описывает детали работы с ChatComponents и ChatFlows, базовую кастомизацию и готовые примеры темы.
На этой странице используются следующие термины (синхронно с Дизайн-система: введение и Компоненты):
| Термин | Что это |
|---|---|
| Токен | Базовый ресурс приложения: R.color.*, R.drawable.*, R.font.*, R.string.*. |
| Палитра | Словарь токенов: ChatColors, ChatImages, ChatTypography. (ChatTexts — legacy-палитра строк, все поля @Deprecated; см. ниже.) |
Компоненты (ChatComponents) | Контейнер общих стилей. Изменения применяются ко всем экранам сразу. |
| Поле компонента | Поле объекта ChatComponents: iconButtonComponent, navigationBarStyle, inputTextComponent, bubbleComponent и др. |
Потоки (ChatFlows) | Контейнер экран-специфичных стилей; полный список — в Потоки. |
| Стиль потока | Конкретное поле внутри потока: chatFlow.navigationBar.backButton, searchFlow.searchBar.textInput и т. п. |
Поддерживаются только параметры, явно указанные в сигнатурах ChatComponents и его полей. Поля, добавленные через рефлексию или внутренние механизмы SDK, не являются частью публичного API. Для класса ChatTexts весь механизм legacy и помечен @Deprecated — используйте strings.xml (см. Локализация).
Часть полей ChatConfig (searchEnabled, linkPreviewEnabled, voiceRecordingEnabled, autoScrollToLatest и др.) переопределяется серверной конфигурацией: клиентские значения применяются только как fallback, когда сервер не прислал своего. Не полагайтесь на эти поля в production — см. Известные ограничения.
Сигнатура ChatComponents
ChatComponents — data class с пятью параметрами:
data class ChatComponents(
val context: Context,
val colors: ChatColors = ChatColors(),
val images: ChatImages = ChatImages(),
val text: ChatTexts = ChatTexts(), // ← legacy, все поля @Deprecated
val typography: ChatTypography = ChatTypography()
)
У всех параметров кроме context есть значения по умолчанию, поэтому в примерах ниже мы передаём только то, что переопределяем.
ChatTexts устарел целикомВсе поля ChatTexts помечены @Deprecated с сообщением «Переопределите ключи в файле strings». В новых интеграциях оставляйте параметр со значением по умолчанию (ChatTexts()) и переопределяйте строки через strings.xml (ключи ecc_*) — см. Локализация. Точные имена полей, если они вам всё-таки нужны для миграции, — в справочнике API на Dokka.
Кастомизация полей ChatComponents
Каждое поле ChatComponents (iconButtonComponent, inputTextComponent, bubbleComponent, imageComponent, messageStatusesComponent, navigationBarStyle и др.) — это var, который можно изменить через apply { ... } после создания. Изменения применяются ко всем экранам сразу. Полный список — в Компоненты.
Например, чтобы глобально заменить иконку и цвет кнопки «назад» на всех экранах SDK:
val components = ChatComponents(applicationContext, colors = yourColors).apply {
iconButtonComponent.apply {
backBtnImage = R.drawable.ic_your_back // @DrawableRes
backButtonColor = R.color.your_brand_main // @ColorRes
}
}
Поля iconButtonComponent (backBtnImage, backButtonColor, chatToolbarInverseIconTintColor, quoteClearIconColor и др.) аннотированы @DrawableRes/@ColorRes и принимают идентификаторы ресурсов вашего приложения.
Если вам нужно переопределить кнопку только на одном экране (например, в чате, но не в галерее) — используйте ChatFlows, см. Потоки.
Конструкторы ChatTheme
ChatTheme — обычный class (не data class) с тремя конструкторами. Выбирайте форму вызова по уровню кастомизации:
// 1. Минимальный: только цвета / иконки / шрифты — для большинства интеграций.
ChatTheme(
context: Context,
colors: ChatColors = ChatColors(),
images: ChatImages = ChatImages(),
texts: ChatTexts = ChatTexts(), // legacy, см. выше
typography: ChatTypography = ChatTypography()
)
// 2. Через готовый ChatComponents — когда настраиваете поля компонентов (например, navigationBarStyle).
ChatTheme(chatComponents: ChatComponents)
// 3. Через готовый ChatFlows — когда точечно меняете стили потоков (chatFlow, searchFlow и т. д.).
ChatTheme(flows: ChatFlows)
Формы иерархичные — выбирайте одну по уровню кастомизации: палитры токенов (форма 1), компоненты (форма 2) или потоки (форма 3). Каждая следующая форма «оборачивает» предыдущую: ChatFlows строится из ChatComponents, а ChatComponents — из палитр. Стиль потока имеет приоритет над одноимённым полем компонента, поле компонента — над значением из палитры.
Базовая кастомизация
Определите цвета и изображения, переопределив только нужные параметры:
val lightColors = ChatColors(
main = R.color.your_light_main,
searchingProgressLoader = R.color.your_light_main,
bodyIconsTint = R.color.your_light_main,
incomingText = R.color.your_black,
incomingTimeText = R.color.your_light_time_text,
outgoingTimeText = R.color.your_light_time_text,
outgoingText = R.color.your_black,
incomingBubble = R.color.your_white,
outgoingBubble = R.color.your_light_outgoing_bubble,
toolbarText = R.color.your_white,
messageSendingStatus = R.color.your_light_icons,
messageSentStatus = R.color.your_light_icons,
messageDeliveredStatus = R.color.your_light_icons,
messageReadStatus = R.color.your_light_icons,
messageFailedStatus = R.color.your_light_icons,
incomingLink = R.color.your_light_links,
outgoingLink = R.color.your_light_links,
toolbar = R.color.your_light_main,
statusBar = R.color.your_light_statusbar,
menuItem = R.color.your_light_main
)
Соберите ChatComponents, передав цвета и изображения. Поля компонентов можно дополнительно настроить через apply:
val lightChatComponents = ChatComponents(
applicationContext,
colors = lightColors,
images = lightImages
).apply {
navigationBarStyle = navigationBarStyle.copy(closeButtonEnabled = false)
}
Создайте тему и установите её при инициализации SDK:
chatLightTheme = ChatTheme(lightChatComponents)
init()Поля theme и darkTheme должны быть установлены до вызова ChatCenterUI.init(...). Установка темы после init() не применится к уже созданному UI — это типичная причина «тема молча не работает».
// chatCenterUI — поле вашего Application / Activity (например, lateinit var).
// chatConfig создаётся по примеру из quick_start.md.
chatCenterUI = ChatCenterUI(applicationContext).apply {
theme = chatLightTheme
darkTheme = chatDarkTheme
init("YOUR_PROVIDER_UID", "YOUR_APP_MARKER", chatConfig)
}
У метода init(...) две перегрузки: с appMarker (как выше) и без него — init(providerUid, config). appMarker нужен, когда у вас несколько Android-приложений под одним providerUid (например, prod и staging); если приложение одно, используйте форму без appMarker.
Точечная кастомизация через ChatFlows
ChatFlows собирает стили всех потоков (chatFlow, searchFlow, galleryFlow, …) и доступен на запись через apply { ... }. Чтобы переопределить, например, только кнопку «назад» в чате:
val flows = ChatFlows(ChatComponents(applicationContext)).apply {
// меняем кнопку «назад»
chatFlow.navigationBar.backButton = IconButtonChatStyle(
IconButtonColorStyle(
iconTintColor = R.color.blue_color
),
R.drawable.ic_cloud
)
// центрируем текст в тулбаре
chatFlow.navigationBar.centerToolbarText = true
}
chatLightTheme = ChatTheme(flows) // экземпляр темы с точечно переопределёнными стилями потоков
copy(), а когда прямое присвоение- Прямое присвоение (
chatFlow.navigationBar.backButton = ...) — подходит для замены объекта целиком (стиль потока или поле компонента). copy()— необходим для изменения отдельных полей data-класса, у которых поле объявлено какval(или для пакетного изменения сразу нескольких полей):Прямое присвоение полюsearchFlow = searchFlow.copy(backgroundColor = R.color.your_search_bg)valне даст эффекта; дляvar-полей оба варианта работают.
Например, чтобы переопределить подсказку поля ввода только на экране поиска:
val flows = ChatFlows(ChatComponents(applicationContext)).apply {
searchFlow.searchBar.textInput?.placeholderTextResId = R.string.your_search_hint
}
placeholderText устарелИспользуйте placeholderTextResId: Int? (@StringRes) — он имеет приоритет над placeholderText: String? и корректно работает с локализацией. Поле placeholderText помечено @Deprecated.
Если же цвет текста нужно изменить для всех полей ввода сразу (а не только в поиске), используйте поле компонента inputTextComponent объекта ChatComponents (lightChatComponents определён выше):
ChatTheme(
lightChatComponents.apply {
inputTextComponent.inputMessageColor = R.color.your_blue
}
)
Живой пример настройки темы — в демо-приложении. Все публичные классы, методы и поля с типами и аннотациями — в справочнике API на Dokka, сгенерированном из исходников SDK.
Готовый пример темы (светлая + тёмная)
Ниже — production-ready пример настройки тем, охватывающий частые кастомизации.
chatCenterUI— поле вашегоApplication/Activity(например,lateinit var chatCenterUI: ChatCenterUI).chatConfigсоздаётся по примеру из Быстрый старт:ChatConfig(transportConfig, networkConfig). Builder-API не предусмотрено.- Поле
fullScreenModeобъектаChatFlowпомечено@Deprecatedи не используется в новых интеграциях — задавать его не нужно.
// --- Светлая тема ---
val lightColors = ChatColors(
main = R.color.your_brand_main,
incomingBubble = R.color.your_incoming_bubble,
outgoingBubble = R.color.your_outgoing_bubble,
toolbar = R.color.your_toolbar_bg,
toolbarText = R.color.your_toolbar_text,
incomingText = R.color.your_incoming_text,
outgoingText = R.color.your_outgoing_text,
)
val lightImages = ChatImages(
logoImage = R.drawable.ic_your_brand_logo,
pushIcon = R.drawable.ic_your_push_icon,
)
val lightComponents = ChatComponents(
context = applicationContext,
colors = lightColors,
images = lightImages
).apply {
navigationBarStyle = navigationBarStyle.copy(
closeButtonEnabled = false
)
}
val lightFlows = ChatFlows(lightComponents)
val chatLightTheme = ChatTheme(lightFlows)
// --- Тёмная тема ---
val darkColors = ChatColors(
main = R.color.your_dark_main,
incomingBubble = R.color.your_dark_incoming_bubble,
outgoingBubble = R.color.your_dark_outgoing_bubble,
toolbar = R.color.your_dark_toolbar_bg,
toolbarText = R.color.your_white,
incomingText = R.color.your_white,
outgoingText = R.color.your_white,
chatBackground = R.color.your_dark_background,
)
val darkComponents = ChatComponents(
context = applicationContext,
colors = darkColors,
images = lightImages // иконки можно переиспользовать
).apply {
navigationBarStyle = navigationBarStyle.copy(
closeButtonEnabled = false
)
}
val darkFlows = ChatFlows(darkComponents)
val chatDarkTheme = ChatTheme(darkFlows)
// --- Инициализация ---
chatCenterUI = ChatCenterUI(applicationContext).apply {
theme = chatLightTheme
darkTheme = chatDarkTheme
init("YOUR_PROVIDER_UID", "YOUR_APP_MARKER", chatConfig)
}
Экран-специфичная кастомизация (все 8 потоков: chatFlow, searchFlow, galleryFlow, filesFlow, imageFlow, popupsFlow, balloonsChatStyle, bottomMenuChatFlow) — см. Потоки (Flows).
FAQ
Нужно ли пересоздавать ChatTheme при смене темы системы (light/dark switch)?
Нет, если речь о переключении между уже установленными theme и darkTheme. SDK определяет текущий режим через AppCompatDelegate.getDefaultNightMode() и Configuration.UI_MODE_NIGHT_MASK при каждом открытии чата и выбирает соответствующую палитру. Достаточно вызвать AppCompatDelegate.setDefaultNightMode(...) — стандартный механизм Android пересоздаст Activity, и SDK подхватит нужную тему.
Это не относится к runtime-замене самого объекта theme = newTheme: переприсвоение после init() не применится к уже открытому чату. Если вы хотите подменить палитру (например, после загрузки brand-настроек из API), задайте новые theme / darkTheme до того, как чат будет открыт пользователем.
Что произойдёт, если я не задам поле ChatColors / ChatImages / ChatTypography?
Используется default SDK. Все поля этих классов имеют тип Int (non-nullable, @ColorRes / @DrawableRes) с предустановленным значением (внутренние ресурсы с префиксом ecc_). Передать null нельзя; чтобы оставить default, просто не указывайте параметр в конструкторе:
ChatColors(main = R.color.your_main /* остальные поля останутся default */)
Конфликтует ли SDK с темой моего Application / Activity (AppCompatTheme, MaterialTheme)?
Нет. SDK устанавливает собственную тему для своих Activity (наследуется от Theme.MaterialComponents.Light.NoActionBar.Bridge). Тема, заданная вашим приложением, на UI SDK не влияет. Изменить внешний вид UI чата можно только через ChatColors, ChatImages, ChatComponents, ChatFlows, описанные выше.
Где посмотреть default-значения SDK?
В справочнике API на Dokka — у каждого поля data-класса ChatColors / ChatImages / ChatTypography показано default-значение. Все внутренние ресурсы SDK имеют префикс ecc_ (например, R.color.ecc_green_83b144, R.drawable.ecc_ic_arrow_back_white_24dp).
Связанные разделы
- Дизайн-система: обзор — уровни кастомизации, ключевые понятия, архитектура темы.
- Цвета — таблица
ChatColorsпо категориям (toolbar, messages, input, push и др.). - Типографика —
ChatTypography: 6 размеров + 20 точек подмены TTF-шрифтов. - Изображения —
ChatImages: drawable по категориям (toolbar, input, messages, опросы и т. п.). - Компоненты — инфографика элементов чата, приоритеты темизации, типичные сценарии кастомизации.
- Потоки (Flows) — экран-специфичная кастомизация: chat / search / gallery / files / image / popups / balloons / bottomMenu.
- Доступность — TalkBack, контраст, RTL.
- Известные ограничения — параметры с приоритетом серверной настройки.