Translucent на андроид и adjustResize

  • Tutorial


Возможность использовать translucent в андроид появилась ещё в KITKAT. И выглядит в правильном дизайне это довольно эффектно. А с появлением моды на девайсы с "Чёлками", кажется, просто необходимой вещью в любом тёплом ламповом стартапчике.


Давайте представим ситуацию: вы запилили офигительно красивый, скроллящийся под StatusBar и NavigationBar дизайн. И вот вы добавляете поле ввода и понимаете, что adjustResize у вас не работает.


Вы можете:


  1. Забить, – пользователь сам закроет клавиатуру, чтобы посмотреть что под ней.
  2. Отказаться от translucent, стиль – это не ваше, всё будет олдово, надёжно, как у всех.
  3. Как только пользователь начинает скроллить, скрывать клавиатуру. Вы молодец! Всё правильно сделали, skype даже под ios так делает! А там и прозрачности-то нет.
  4. Вынести все поля ввода на отдельные экраны. Как бонус — каждый лишний переход на экран, минус удобство и конверсия.
  5. Запилить свой adjustResize.

Все сложности translucent


При реализации translucent есть несколько сложностей:


  1. Нужно учитывать дизайн для девайсов меньше KITKAT (думаю что в 2019 году, это уже почти не актуально, особенно для новых проектов). Пожалуй, для девайсов меньше LOLLIPOP может овчинка выделки не стоит? Там нельзя получить прозрачный NavigationBar и "Чёлок" на таких девайсах тоже не было.
  2. Если уж вы задумались о translucent, то скорее всего хотите что-то сложнее, чем статичный задний фон, что-то скролящееся под StatusBar и NavigationBar, что-то что при помощи fitsSystemWindows не сделать, а значит высоту StatusBar и NavigationBar придётся подставлять динамически.
  3. И наконец главное: adjustResize работает только без translucent или для тех View которые fitsSystemWindows.

О чём речь, и как это должно работать



Решение проблемы


Вроде бы решение простое: не работает adjustResize, значит надо реагировать на открытие клавиаруты самим. Но вот беда android не предоставляет не только высоту открывшейся клавиатуры (а она может быть разная даже для разных EditText полей), но даже сам факт её открытия или закрытия. Официального способа нет. Как же так google?


Решение конечно есть! А когда у вас появляется информация о текущей высоте клавиатуры вы можете сделать с ней что захотите: добавить padding или margin снизу для тех View, которые должны реагировать на клавиатуру и вот кастомный adjustResize готов.


Код


Для того, чтобы понять, что была открыта клавиатура, используется OnGlobalLayoutListener. Вставлять куски кода в пост не вижу смысла. Зачем писать 100 строк о том, что выражается в коде за 50?
Решение проблемы представлено в репозитории.


Присмотритесь к KeyboardHeightProvider и BaseTranslucentActivity.


Проект максимально простой, понятный, в нём нет ничего лишнего, что не относится к проблеме.
Есть пример для простого TextView, RecyclerView и ScrollView. Эта же техника была проверена и отлично работает и для NestedScrollView, NestedFragments, CoordinatorLayout, ViewPager и т.п.


P.s.: https://developer.android.com/reference/android/view/WindowInsets решает проблему с клавиатурой не хуже.

Поделиться публикацией

Комментарии 8

    +1
    У меня еще при сочетании translucent и adjustResize при открытой клавиатуре слетает позиционирование задника за тулбаром (FrameLayout с заливкой или картинкой, чтобы был эффект захождения тулбара под статусбар): он становится в два раза больше. Я так и не понял почему.
      0
      Надо разметку смотреть) А там нет всяких fitsSystemWindows?
        0
        Есть такой.

        Разметка самая простая:

            LinearLayout (orientation=vertical)
            +---FrameLayout (fitsSystemWindows=true)
                +---Toolbar
            +---FrameLayout (weight=1)
        
      0

      Привет!
      Похожую проблему описывали в этой статье.


      Там идет ссылка на выступление Криса Бейнса.
      Вот тут выжимка из его доклада.


      Можно попробовать заменить грамоздкий OnGlobalLayoutListener на менее затратный setOnApplyWindowInsetsListener или как вариант выключать adjustResize для данного экрана.

        0
        К сожалению WindowInsets нам не поможет получить то, что мы хотим.
          0

          Я пробросил дочерним view, информацию о смещении, и adjustResize у меня работает без проблем.

            0
            Действительно можно и так! Спасибо! Я надеялся, что кто-то меня поправит и напишет, что можно по-другому!
              0

              Пожалуйста! Рад был помочь)

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

      Самое читаемое