
Каждый Android-разработчик сталкивается с задачей обучения пользователей новым функциям или помощи в навигации по интерфейсу. Традиционные всплывающие окна или сообщения могут быть навязчивыми. Конечно же есть способ элегантно подсвечивать элементы UI и предоставлять контекстную помощь. Встречайте TAO Bubbles – легковесную библиотеку для Jetpack Compose, созданную для отображения настраиваемых «пузырей«, «подсказок» или «тултипов«, которые могут указывать на конкретные UI-компоненты.TAO Bubbles прекрасно подходит для создания пошаговых руководств, демонстрации новых возможностей или предоставления контекстно-зависимой справки прямо в вашем приложении.
P.S. Проект создавался во время изучения Jetpack Compose, так что конструктивная критика и pull requests с улучшениями приветствуется ).
Ключевые особенности TAO Bubbles для Jetpack Compose
-
Полная кастомизация внешнего вида: Управляйте положением стрелки, размером, радиусом углов, цветами, границами и многим другим. Вы можете легко адаптировать стиль подсказок под дизайн вашего приложения. Внутри можно расположить любой ваш макет Composable.
-
Гибкое позиционирование: Подсказки могут указывать на любую сторону целевого composable-компонента (LEFT, RIGHT, TOP, BOTTOM).
-
Адаптация к границам экрана: пузыри Bubble автоматически корректируют свое положение, чтобы оставаться в пределах видимости экрана, обеспечивая отличный пользовательский опыт на любых устройствах.
-
Последовательный показ: Используйте BubbleShowController для легкого отображения серии подсказок одна за другой, проводя пользователя через несколько шагов.
-
Анимации появления/исчезновения: Плавные и настраиваемые анимации для появления и исчезновения подсказок делают взаимодействие более живым.
-
Затемнение фона (Scrim): Опциональный слой затемнения фона помогает сфокусировать внимание пользователя на подсказке.
-
Декларативный API: Библиотека разработана с учетом современных практик Jetpack Compose, предлагая простой и интуитивно понятный API.
-
Легкое использование: Никаких сложных конструкций. Добавление к существующему проекту очень простое.

Как это работает?
Пример использования (одиночный Bubble):
Определяете общие стили для всех ваших «пузырей» или для конкретной группы.
val settings = BubblesSettings( scrimColor = Color(0x22002EFF), // Цвет затемнения фона backgroundColor = OrangeVeryLight, // Цвет фона подсказки bubbleBorderColor = Color.Black, // Цвет рамки bubbleBorderWidth = 2.dp // Толщина рамки ... и так далее )
Подготавливаете данные для каждой подсказки.
val bubbleData = BubbleData( id = "Intro_Feature", // Уникальный ID для сохранения состояния (показана/скрыта) arrowPosition = ArrowPosition.BOTTOM, // С какой стороны целевого объекта прилегает стрелка и подсказка content = { onDismissClick, onStopShowRequest -> // Здесь размещается любой ваш Composable-контент для подсказки // onDismissClick - функция вызываемая по закрытию подсказки // onStopShowRequest - функция для остановки всей последовательности (если используется BubbleShowController) Text("Это важная новая кнопка!") } )
И используете эти данные в своем коде:
@Composable fun SingleBubbleExample() { var showBubble by remember { mutableStateOf(true) } var targetRect by remember { mutableStateOf<Rect?>(null) } // Rect целевого компонента Box(modifier = Modifier.fillMaxSize()) { Button( onClick = { showBubble = !showBubble }, modifier = Modifier .align(Alignment.Center) .onGloballyPositioned { coordinates -> // Получаем геометрию компонента, к которому будет привязана подсказка targetRect = coordinates.boundsInWindow() } ) { Text("Показать подсказку") } Bubble( targetComponentRect = targetRect, // Передаем Rect цели bubbleData = bubbleData, // Наши данные для подсказки settings = settings, // Наши настройки стиля isVisible = showBubble, // Управляем видимостью onDismissRequest = { showBubble = false } // Действие при закрытии ) } }
Настройка показа последовательных подсказок.
Показ большого количества подсказок не сильно сложнее. Для настройки используем BubbleShowController.
Подготавливаем список (или по одному) BubbleData для каждой подсказки:
val testBubbles = listOf( BubbleData( id = "Step_1", arrowPosition = ArrowPosition.BOTTOM, content = { onDismissClick, onStopShowRequest -> MyContent("Подсказка 1: Нажмите здесь", onDismissClick, onStopShowRequest) } ), BubbleData( id = "Step_2", arrowPosition = ArrowPosition.LEFT, content = { onDismissClick, onStopShowRequest -> MyContent("Подсказка 2: Затем проверьте это", onDismissClick, onStopShowRequest) } ), BubbleData( id = "Step_3", arrowPosition = ArrowPosition.RIGHT, content = { onDismissClick, onStopShowRequest -> MyContent("Подсказка 3: И наконец, сюда!", onDismissClick, onStopShowRequest) } ) ) // MyContent - ваш кастомный Composable для содержимого подсказки @Composable fun MyContent(text: String, onDismiss: () -> Unit, onStopShow: () -> Unit) { Column(horizontalAlignment = Alignment.CenterHorizontally) { Text(text) Button(onClick = onDismiss) { Text("Далее") } // Button(onClick = onStopShow) { Text("Завершить тур") } // Если нужно } }
И используем подготовленные данные в основном коде связывая каждый BubbleData с целевым объектом :
@Composable fun BubbleSequenceExample() { // Подготовка показа val bubblesSettings = remember { testSettings } // Используем ранее созданные настройки val bubblesData = remember { testBubbles } // Используем ранее созданные данные для каждой подсказки. Но можно и по одному. val bubbleShowController = rememberBubbleShowController( // Контроллер показа settings = bubblesSettings, bubbles = bubblesData, onFinished = { // Действия после завершения всех подсказок Log.d("BubbleShow", "Все подсказки показаны!") } ) Box( modifier = Modifier .fillMaxSize() .background(Color(0xFFE0F7FA)) ) { // Ваши UI компоненты, к которым будут привязаны подсказки Box( modifier = Modifier .align(Alignment.TopStart) .padding(16.dp) .size(100.dp) // Связываем компонент с данными подсказки через контроллер .assignBubble(controller = bubbleShowController, bubbleData = bubblesData[0]), contentAlignment = Alignment.Center ) { Text("Элемент 1", color = Color.Black) } Box( modifier = Modifier .align(Alignment.TopEnd) .padding(16.dp) .size(100.dp) .assignBubble(controller = bubbleShowController, bubbleData = bubblesData[1]), contentAlignment = Alignment.Center ) { Text("Элемент 2", color = Color.Black) } Box( modifier = Modifier .align(Alignment.BottomStart) .padding(16.dp) .size(100.dp) .assignBubble(controller = bubbleShowController, bubbleData = bubblesData[2]), contentAlignment = Alignment.Center ) { Text("Элемент 3", color = Color.Black) } // Кнопка для перезапуска показа Button( modifier = Modifier .align(Alignment.Center) .padding(top = 224.dp), onClick = { bubbleShowController.restartShow() }) { Text("Перезапустить показ") } // Отображаем текущую подсказку из контроллера // Composable Bubble с контроллером автоматически управляет видимостью и настройками. bubbleShowController.ShowBubbles() } }
Модификатор .assignBubble() связывает ваши UI-компоненты с соответствующими данными подсказок в контроллере. Контроллер затем сам позаботится об определении targetComponentRect для каждой подсказки.
Нужно больше настроек?
Если вы предпочитаете иметь полный контроль и кастомизацию каждого пузыря в списке для показа, то используйте BubbleShowControllerExtended для контроля и BubbleDataExtended для настройки каждого пузыря.
Заключение
TAO Bubbles для Jetpack Compose – это простой, но мощный инструмент для создания интерактивных подсказок и туров по приложению. Благодаря гибкой настройке и удобному API, вы сможете значительно улучшить пользовательский опыт, помогая пользователям осваивать функционал вашего приложения легко и непринужденно.
Попробуйте TAO Bubbles в своем следующем проекте!
Скачать последний релиз и код демо-приложения https://github.com/lordtao/android-tao-bubbles
Лицензия MIT
ссылка на оригинал статьи https://habr.com/ru/articles/936122/
Добавить комментарий