Как стать автором
Поиск
Написать публикацию
Обновить

TAO Bubbles: элегантные и настраиваемые подсказки для ваших Jetpack Compose приложений

Уровень сложностиСредний
Время на прочтение5 мин
Количество просмотров188

Каждый 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

Теги:
Хабы:
0
Комментарии0

Публикации

Ближайшие события