Обновить
5.62

Jetpack Compose *

декларативный UI Framework для Android

Сначала показывать
Порог рейтинга

Как я сделал blur и линзу в Jetpack Compose

Всем привет! Меня зовут Владимир, я мобильный разработчик в «Финам». В одном из недавних проектов нужно было добавить в интерфейс Jetpack Compose визуальные эффекты поверх контента, например размытый хедер или движущуюся «лупу». 

Обычно такие приемы встречаются в играх, где весь экран — это фактически полотно для рисования OpenGL. В классической XML-разметке UI я с таким не сталкивался, поэтому пришлось довольно глубоко погрузиться во внутреннюю кухню Compose. Этот разбор может быть полезен тем, кто решает похожие задачи.

Сначала на Stack Overflow я нашел неплохой пример создания эффекта размытия на определенном участке экрана — к сожалению, это решение не было универсальным и зависело от верстки. Однако мое внимание привлекли два класса из фреймворка: RenderNode и GraphicsLayer

Если коротко, можно захватить часть экрана через GraphicsLayer, а в RenderNode записать контент. Но перед этим его можно обработать. После обработки метод drawWithContent() выводит результат в canvas. 

Сначала я попытался модифицировать эффект размытия из ответа на Stack Overflow, затем сделал размытие в форме круга, который движется вслед за пальцем, и постепенно пришел к окончательному варианту с движущейся прозрачной линзой. Код для отрисовки эффекта я показал в статье.

В результате можно получить эффект линзы, которая будет перемещаться за пальцем, если водить им по экрану. 

Какие выводу я могу сделать:

  • в Compose можно делать крутые визуальные эффекты, если покопаться в RenderNode;

  • это неочевидный, но мощный инструмент, он дает простор для кастомизации.

Мой пример не самый изобретательный, но способ, который я показал, открывает почти безграничные возможности для реализации визуальных эффектов в Android-разработке, чем мы в «Финам» и пользуемся очень активно в наших финтех-проектах. Итоговый результат оформил в GitHub-репозитории — берите и пробуйте в своих проектах.

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

rememberSaveable Compose

rememberSaveable ведет себя так же, как и remember, сохраняя состояние при рекомпозиции, но также позволяет пережить поворот экрана

Все типы данных, которые можно добавить в Bundle, сохраняются автоматически. Если требуется сохранить то, что нельзя добавить в Bundle, есть несколько вариантов

MapSaver

ListSaver

Parcelize Пример ниже

@Parcelize
data class City(val name: String, val country: String) : Parcelable

@Composable
fun CityScreen() {
    var selectedCity = rememberSaveable {
        mutableStateOf(City("Madrid", "Spain"))
    }
}

Теги:
Всего голосов 1: ↑1 и ↓0+1
Комментарии0

Таймер на LaunchedEffect в Compose

LaunchedEffect(keyN) запустит свою лямбду, в начале композиции. LaunchedEffect будет запускать свою лямбду снова каждый раз, когда изменится один из заданных ключей keyN

Причем в лямбде будет находится coroutine context

@Composable
fun Timer() {
    var seconds by remember { mutableStateOf(0) }

    LaunchedEffect(seconds) {
            delay(1000)
            seconds++
        }

    Text(text = "Seconds: $seconds")
}

mutableStateOf - Создает State при изменении которого compose функция перезапускается

remember - сохраняет этот State при каждом перезапуске функции

remember + mutableStateOf

Теги:
Рейтинг0
Комментарии0