Pull to refresh

Comments 17

Так в результате у вас осталось поведение от самого BottomSheetDialog(свайп вверх/вниз)?
Или каждый фрагмент просто визуально косит под BottomSheetDialog?

Поведение осталось от BottomSheetDialog. По факту, у нас получился честный BottomSheetDialogFragment, просто в него с помощью его childFragmentManager добавляются фрагменты. В теории, даже смена состояний должна работать (но я не пробовал)
а как вы применяете скругление углов? Fragment внутри fragmentContainerView расположится на всю высоту и перекроет углы боттом щита. Как то темой заставляете скруглять fragmentContainerView?
Сам FragmentContainerView всегда остаётся прозрачным. Чтобы добиться скругления углов и не терять его при анимации, можно покрасить со скруглениями корневой элемент BottomSheetDialogFragment'а и либо не красить корневой элемент дочерних фрагментов, либо установить ему background с такими же скруглёнными краями. Пример можно пощупать на гитхабе
Получается некая привязка фрагментов к диалогу, в котором они используются. Спасибо за ответ, идея понятна =). Крутая шторка получилась, респект. В проекте единственное не хватает обработки аппаратной кнопки назад, важная вещь всё таки. Можно повесить слушатель нажатий на кнопки в диалоге и при кнопке назад вызывать на childFragmentManager popBackStack(), если кому то интересно.
Круто сделали! Без анимаций совсем не то. Но вот вопрос, с какой версии android у вас поддержка, и что делать с версиями ниже 5.0?
Не вспоминать про них…
Спасибо! Устройства версии ниже 5.0 поддержать будет довольно трудно, так как transition api доступен только начиная с Lollipop. Для нас это не было проблемой, потому что мы сразу решили такие устройства оставить без данной анимации. Я думаю, если появилась задача поддержать pre-lollipop, то мы использовали бы тот же подход «зафиксировать высоту, потом анимировать», только делать это пришлось бы не с помощью Shared Element Transition, а вручную до и после транзакции фрагментов
забыть про них, и поднять мин апи до 21
private fun prepareFadeInAnimator(view: View): Animator =
ObjectAnimator.ofFloat(view, "alpha", 0f, 1f)

При использовании ObjectAnimator рекомендуется передавать поле не по его имени("alpha", "translationX"), а по его проперти ObjectAnimator.ofFloat(T target, Property<T, Float> property, float… values). Такой вариант избавляет от вызова сеттера этого поля через рефлексию. Так же является типобезопасным, ведь можно легко сделать опечатку "alfa" вместо View.ALPHA или "transletionX" вместо View.TRANSLATION_X.
На примере Plaid от Ника Батчера.


Все эти проперти так же есть и в AppCompat варианте.


Странно конечно что в документации не говорится про такой прием, тем не менее эта тема достаточно часто вскрывалась на конференциях с участием Chet Haase и Romain Guy.

Вы правы (только что посмотрел исходники). Не знал, что в этом случае не будет рефлексии. Спасибо за совет, поправил текст и теперь буду знать про это!

Спасибо за статью! Идея с контейнером-шаред элементом классная, но есть пара пара замечаний по коду внутри:


  1. Не советую использовать зашитые в Android константы для определения размера статус-бара. Это плохая практика, и на различных девайсах от Meizu, Dogee, и прочих нонеймах с кастомными надстройками работать не будет. Советую работать через windowInsets, статей по этому подходу достаточно много, например здесь: https://habr.com/ru/company/surfstudio/blog/464373/
  2. В методе getScreenHeight используется только статус бар, но при этом мы забываем про высоту навигейшн-бара, из-за чего на девайсах с нижним баром навигации, контейнеры улетят вверх.
  3. Высоту и ширину экрана можно получить гораздо проще, без необходимости прибегать к системным сервисам: view.resources.displayMetrics содержит нужную инфу.
Рад, что идея вам понравилась! Спасибо за обратную связь по статье и за ссылку на интересную статью про inset'ы! Позвольте пару мыслей по тем пунктам, о которых вы упомянули:

  1. Вы абсолютно правы, что использовать insets правильнее, чем получать высоту системных отступов (в нашем случае — статус бара) вручную. Но тут есть один момент — «из коробки» BottomSheetDialog не позволяет обрабатывать inset'ы (об этом на своём митапе рассказывали ребята из Redmadrobot, вот ссылка на комментарий и митап). Это происходит из-за fitsSystemWindows=«true» у CoordinatorLayout'а в BottomSheetDialog. Я посчитал, что решение этой проблемы за рамками данной статьи, поэтому остаётся два простых варианта, как рассчитать доступную высоту — из высоты экрана вычесть либо padding'и CoordinatorLayout'а (padding'и установятся автоматически за счет fitsSystemWindows=«true»), либо высоту status bar'а. Я посчитал, что между этими вариантами разницы нет, но возможно лучше было взять использовать padding'и CoordinatorLayout'а
  2. «В методе getScreenHeight используется только статус бар» — всё верно, так и должно быть. Метод Display.getSize(), который я использовал для получения высоты экрана, внутри себя уже убирает некоторые системные выступы из общей высоты, например, он вычитает высоту navigation бара (проверено на устройствах с navigation баром). Возможно, правильнее было бы использовать Display.getRealSize(), который возвращает полный размер экрана, и вычесть высоту и статус бара, и navigation бара (а еще правильнее, еще раз соглашусь с вами, — использовать inset'ы)
  3. Да, можно так, это проще


Я мог что-то упустить, поэтому буду рад дополнительным комментариям :)
UFO just landed and posted this here
Привет! Здорово, что вы обратили на это внимание. На самом деле, приложение рисуется edge-to-edge, а навбар и статус бар покрашены, но покрашены неудачно. Статус бар уже поправлен (просто скрины делались относительно давно), а навбар пока на очереди.

Спасибо за ваш комментарий, рад, что вам понравилась анимация!

А какое решение используете для планшетов? Также BottomSheet?

Мы в нашем приложении не работали над поддержкой планшетов — не было необходимости
Sign up to leave a comment.