Skip to content

Компактная Kotlin-библиотека для Android, которая упрощает работу с системными отступами в сценариях edge-to-edge.

License

Notifications You must be signed in to change notification settings

dapadz/eteinsets

Repository files navigation

EteInsets — Управление системными отступами в Android стало проще

Версия API Лицензия

EteInsets — это компактная Kotlin-библиотека для Android, которая упрощает работу с системными отступами (WindowInsets), особенно в сценариях edge-to-edge. Она предоставляет декларативный DSL, который позволяет легко и предсказуемо управлять реакцией вашего UI на системные панели (status bar, navigation bar) и клавиатуру (IME).

Забудьте о ручном управлении флагами fitsSystemWindows и сложной логике в OnApplyWindowInsetsListener. С EteInsets вы описываете что должно произойти, а не как.

Возможности

  • Декларативный DSL: Простой и читаемый способ описания поведения.
  • Поддержка Edge-to-Edge: Легко заставляет ваше приложение отрисовываться под системными панелями.
  • Анимация клавиатуры (IME): Плавная синхронизация анимации вашего UI с появлением и скрытием клавиатуры.
  • Готовые решения: Встроенные эффекты для самых популярных сценариев.
  • Расширяемость: Возможность создавать собственные эффекты для уникального поведения.
  • Автоматическое управление жизненным циклом: Библиотека сама очищает ресурсы, когда View отсоединяется от окна.

Установка

Добавьте зависимость в ваш build.gradle.kts (или build.gradle):

dependencies { implementation("com.github.dapadz:eteinsets:1.0.0") }

Как это работает?

Библиотека предоставляет функцию-расширение View.insets { ... }. Внутри DSL-блока вы описываете, как View должно реагировать на системные отступы, комбинируя готовые эффекты.

myView.insets { 
    // Здесь вы описываете поведение
}

Библиотека создаёт специальный диспетчер (ImeInsetsDispatcher), который устанавливается на вашу View и управляет всеми эффектами, получая и обрабатывая события системных отступов и их анимаций.

Основные эффекты и примеры использования

1. systemBarsPadding — Работа с системными панелями

Это базовый эффект для реализации edge-to-edge. Он добавляет отступы системных панелей (status bar, navigation bar) к padding вашего View. Это позволяет контенту не залезать под системные элементы, в то время как фон View отрисовывается под ними.

Пример

Чтобы сделать RecyclerView или ConstraintLayout во весь экран, но чтобы его контент начинался ниже status bar и выше navigation bar:

recyclerView.insets { 
    systemBarsPadding(top = true, bottom = true)
}

Результат:

  • paddingTop у recyclerView будет увеличен на высоту status bar.
  • paddingBottom будет увеличен на высоту navigation bar.

-- Здесь будет видео, демонстрирующее, как контент сдвигается, а фон остаётся под панелями --

Модификатор .hideWhenIme()

Частая проблема: при открытии клавиатуры возникает двойной отступ снизу (от системной панели + от клавиатуры). Модификатор .hideWhenIme() плавно убирает отступ системной панели, когда появляется клавиатура.

recyclerView.insets {
    // Применить отступы и плавно убирать нижний отступ, когда появляется IME 
    systemBarsPadding(bottom = true).hideWhenIme() 
}

-- Здесь будет видео: отступ внизу плавно исчезает при появлении клавиатуры и появляется обратно при её скрытии --


2. imeAvoidOverlaps — Подъём View над клавиатурой

Этот эффект предотвращает перекрытие вашего View клавиатурой. Он плавно смещает View вверх синхронно с анимацией появления/скрытия IME.

Пример

bottomButton.insets {
    // Смещать кнопку вверх, чтобы она оставалась над клавиатурой 
    imeAvoidOverlaps()
}

Результат: bottomButton получит paddingBottom, равный высоте клавиатуры, что заставит его "подпрыгнуть" вверх.

-- Здесь будет видео, где кнопка внизу экрана плавно поднимается при появлении клавиатуры --

Параметры imeAvoidOverlaps

  • mode: Способ смещения View.
    • ApplyMode.PADDING_BOTTOM (по умолчанию): добавляет padding снизу.
    • ApplyMode.MARGIN_BOTTOM: добавляет margin снизу.
    • ApplyMode.TRANSLATION_Y: изменяет translationY (смещает визуально, не меняя разметку).
  • overlapOnly:
    • true (по умолчанию): View смещается только на высоту перекрытия. Если клавиатура не достаёт до View, ничего не произойдёт.
    • false: View смещается на полную высоту клавиатуры, даже если она его не перекрывает.
myFloatingView.insets { 
    imeAvoidOverlaps(
        mode = ImeAvoidOverlapsEffect.ApplyMode.TRANSLATION_Y,
        overlapOnly = true 
    )
}

3. keepCenteredUnderIme — Удержание View по центру

Этот эффект удерживает View по центру видимой области экрана, когда появляется клавиатура. Идеально подходит для экранов логина или форм, где логотип или заголовок должны оставаться в центре.

Пример

logoImageView.insets { 
    keepCenteredUnderIme()
}

Результат: При появлении клавиатуры logoImageView плавно сместится вверх, чтобы его центр совпадал с центром пространства между верхом экрана и верхом клавиатуры.

-- Здесь будет видео: логотип в центре экрана смещается вверх при появлении клавиатуры, оставаясь в центре видимой области --


4. use — Создание собственных эффектов

Вы можете создавать собственные эффекты, наследуясь от InsetEffect или AnimatedInsetEffect.

AnimatedInsetEffect даёт доступ к колбэкам анимации (onPrepare, onStart, onProgress, onEnd).

Пример: эффект "Parallax"

Создадим эффект, который будет смещать ImageView вверх с меньшей скоростью, чем поднимается клавиатура, создавая эффект параллакса.

 // 1. Создайте свой эффект
 class ParallaxEffect(private val factor: Float = 0.5f) : AnimatedInsetEffect() { 
     override fun onProgress(
         insets: WindowInsetsCompat,
         animations: List<WindowInsetsAnimationCompat>
     ) { 
         val imeHeight = insets.imeHeight() 
         hostView?.translationY = -imeHeight * factor 
     }
 }

 // 2. Примените его в DSL
 headerImage.insets { 
     use(ParallaxEffect(factor = 0.3f))
 }

-- Здесь будет видео, где фоновое изображение медленно уезжает вверх при появлении клавиатуры --

Управление жизненным циклом

Библиотека автоматически отписывается от всех слушателей, когда View отсоединяется от окна (onDetachedFromWindow), предотвращая утечки памяти.

Если вам нужно прекратить обработку отступов вручную, вы можете сохранить InsetsHandle и вызвать dispose().

val handle = myView.insets { ... }
// Позже, когда это будет необходимо
handle.dispose()

About

Компактная Kotlin-библиотека для Android, которая упрощает работу с системными отступами в сценариях edge-to-edge.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages