Collapsing toolbar android tutorial

Collapsing Toolbar in Android using androidx Jetpack

May 18, 2020 · 3 min read

Androidx is a major upgrade to previously used support libraries, providing backward compatibility across Android versions. In this tutorial, we will use latest androidx jetpack along with material design libraries for captioned UI view.

App bars can be customised to accommodate image, toolbar and can react to different scrolling effects like elements sliding through in and out of view. This is made possible by using Coordinator Layout as parent container, in junction with App bar and CollapsingBar layouts.

CoordinatorLayout allo w s communication between its child views. Here, Collapsing toolbar can be considered as wrapper toolbar for adding additional features. For this to happen, it should be used as child of Appbar and appbar layout has to be a part of CoordinatorLayout, to make the functionality work.

In the picture above, Toolbar and ImageView are encapsulated inside CollapsingToolbar to help customising Toolbar, i.e apply UI behavioural and positional change.

Lets begin with a basic example.

Setup

Add following dependencies in gradle.build file to use aforementioned layouts.

Style.xml

Ensure MaterialComponents based theme is included in style.xml. I have included . NoActionBar since we’ll be explicitly including it activity layout.

I have additionally added background and text colour in colors.xml to give a different look across app. This is optional.

XML Layout

Lets run through our layout example ahead of explanation

app:layout_scrollFlags: To make the toolbar react to the scroll events, it is typically set to “scroll|exitUntilCollapsed”. Other values- expandAlwaysCollapsed,expandAlway,snap,exitUntilCollapsed

app:collapsedTitleGravity: Specifies the gravity of title in the container when collapsed.

app:contentScrim: Specifies drawable or Color value when scrolled sufficiently off screen

app:layout_collapseMode: Specifies how child views of collapsing toolbar layout move when layout is moving. Parallax- moves in parallax fashion, Pin-view placed in fixed position

content_scrolling.xml will have Textview to be displayed below toolbar while scrolling.

Activity

Import below libraries

In addition to existing code, add below snippet inside onCreate() method

Instance of toolbar view is passed as parameter to setSupportActionBar() method to enable toolbar view.

setTitle() and setContentScrimColor() on collapsing layout manager instance changes color and scrim color respectively upon scrolling (Note: Scrim color may also be set within layout resource file).

Источник

Как декларативно описать коллапсирующий тулбар

Хочу представить решение того, как можно описать CollapsingToolbar, с акцентом на читаемости кода. В статье не будет объясняться, что такое и как написать свой CoordinatorLayout.Behavior. Если читателю интересно в этом разобраться, есть много статей, в том числе на хабре. Если разбираться не хочется — ничего страшного: я постарался вынести написание CollapsingToolbar так, чтобы можно было абстрагироваться от CoordinatorLayout.Behavior и OnOffsetChangedListener.

Термины

Зачем понадобилось писать свое решение

Я просмотрел несколько подходов в «интернетах», и практически все были построены следующим образом:

  1. Задается фиксированная высота для AppBarLayout.
  2. Пишется CoordinatorLayout.Behavior, в котором какими-то вычислениями (закешированная высота view складывается с bottom другого view и за вычетом margin умножается на проскролл, вычисленный здесь же) меняют какую-то вью.
  3. Другие вью меняют в OnOffsetChangedListener AppBarLayout-а.
Читайте также:  Android and ios мультиплеер

Вот пример Behavior с описанным подходом, 2.5к звезд на Гитхабе.

Поправить верстку для этого решения можно, но меня смущает другое. Некоторые вью управляются через OnOffsetChangedListener, некоторые — через Behavior, что-то работает из коробки. Разработчику, чтобы понять всю картину, придется пробежаться по множеству классов, и если для новой вью придется добавить поведение, которое зависит от других Behavior-ов и от вью, которые изменяются в OnOffsetChangedListener, могут вырасти костыли и баги на ровном месте

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

В гифке в начале статьи видно, как по нажатию на кнопку скрывается TextView — и NestedScroll подтягивается выше, чтобы не возникало пустого пространства).

Как это сделать? Решения, которые первыми приходят на ум, — написать еще один CoordinatorLayout.Behavior для NestedScroll (сохранив логику базового AppBarLayout.Behavior) или засунуть тулбар в AppBarLayout и менять его на OnOffsetChangedListener. Я пробовал оба решения, и получался завязанный на детали реализации код, с которым довольно сложно будет разобраться кому-то другому и нельзя будет переиспользовать.

Буду рад, если кто-то поделится примером, где такая логика реализована «чисто», а пока покажу свое решение. Идея в том, чтобы иметь возможность декларативно описать в одном месте, какие вьюхи и как должны себя вести.

Как выглядит апи

Итак, для создания CoordinatorLayout.Behavior нужно:

  • унаследовать BehaviorByRules;
  • переопределить методы, возвращающие AppBarLayout, CollapsingToolbarLayout и длину скролла (высоту AppBarLayout).
  • переопределить метод setUpViews — описать правила, как вью будет себя вести при измененнии проскролла аппБара.

TopInfoBehavior для тулбара из гифки в начале статьи будет выглядеть так (далее в статье объясню, как это работает):

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

Задача сводится к написанию правил:

Тут все ясно — приходит float-значение от 0 до 1, отражающее процент проскролла ActionBar, приходит вью и ее первоначальный стейт. Интереснее выглядит BaseBehaviorRule — правило, от которого наследуются другие базовые правила.

Для базовых правил определяется размах значений (min, max) и interpolator. Этого хватит для того, чтобы описать практически любое поведение.

Допустим, мы хотим задать альфу для нашего вью в диапазоне 0.5 до 0.9. Также мы хотим, чтобы вначале скролла вью быстро становилась прозрачной, а затем скорость изменений падала.
Правило будет выглядеть так:

А вот реализация BRuleAlpha:

И, наконец, код BehaviorByRules. Для тех, кто писал свой Behavior, все должно быть очевидно (кроме того, что внутри onMeasureChild, об этом расскажу ниже):

Так что там с onMeasureChild?

Это нужно для решения проблемы, о которой писал выше: если какая-то часть тулбара исчезает, NestedScroll должен подъехать выше. Чтобы он подъехал выше, нужно уменьшить высоту CollapsingToolbarLayout.

Есть еще один неочевидный метод — canUpdateHeight. Он нужен, чтобы можно было разрешить наследнику задать правило, когда нельзя менять высоту. Например, если view, от которого зависит высота, в данный момент скрыта. Не уверен, что это покроет все кейсы, но если у кого есть идеи, как сделать лучше, — отпишите, пожалуйста, в комментарии или в личку.

Источник

Овладение Coordinator Layout

На презентации Google I/O 15, компания Google представила новую версию библиотеки поддержки которая реализует несколько компонентов, сильно связанных со спецификациями Material Design, среди этих компонентов вы можете найти новые типы ViewGroup такие как AppbarLayout , CollapsingToolbarLayout и CoordinatorLayout .

Читайте также:  Как открыть системные файлы андроида

При правильном комбинировании и настройке данные Viewgroup могут быть очень мощным инструментом, по этому я решил написать статью с некоторыми настройками и советами.

CoordinatorLayout

Как и предполагает его название, цель и философия этой ViewGroup является координация view элементов, которые находятся внутри него.

Рассмотрим следующую картинку:

В этом примере можем видеть как view элементы размещены друг относительно друга, не прибегая к детальному просмотру, мы видим как одни View зависят от других. (мы поговорим об этом позже).

Это будет простейшая структура использования CoordinatorLayout :

Рассмотрим скелет данного layout. У этого CoordinatorLayout имеется только три дочерних элемента: AppbarLayout , прокручиваемый view и закрепленный FloatingActionBar .

AppBarLayout

Проще говоря, AppBarLayout это LinearLayout на стероидах, их элементы размещены вертикально, с определенными параметрами элементы могут управлять их поведением, когда содержимое прокручивается.

Это может прозвучать запутано сначала, но как, — «Лучше один раз увидеть, чем сто раз услышать», к вашему вниманию .gif-пример:

В данном случае AppBarLayout это синяя view, размещенная под исчезающим изображением, она содержит Toolbar , LinearLayout с заголовком и подзаголовком и TabLayout с несколькими вкладками.

Мы можем управлять поведением элементов AppbarLayout с помощью параметров: layout_scrollFlags . Значение: scroll в данном случае присутствует почти во всех элементах view, если бы этот параметр не был указан ни в одном из элементов AppbarLayout, он остался бы неизменным, позволяя прокручиваемому контенту проходить позади него.

Со значением: snap , мы избегаем попадания в полу-анимационного-состояния, это значит, что анимация всегда скрывает или отображает полный размер view.

LinearLayout который содержит заголовок и подзаголовок будет всегда отображен при прокручивании вверх, ( enterAlways значение), и TabLayout будет видим всегда так как на него не установлен ни один флаг.

Как видите настоящая мощь AppbarLayout определяется должным управлением его флагами прокрутки в определенных view.

Все эти параметры доступны в документации Google Developers. В любом случае, я рекомендую поиграть с примерами. В конце статьи размещены ссылки на репозитории Github с реализацией примеров.

Флаги AppbarLayout

SCROLL_FLAG_ENTER_ALWAYS : При использовании флага, view будет прокручиваться вниз не зависимо от других прокручиваемых view.
SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED : Дополнительный флаг для ‘enterAlways’, который изменяет возвращаемый view к изначально прокручиваемому, при исчезновении высоты.
SCROLL_FLAG_EXIT_UNTIL_COLLAPSED : При выходе, view будет прокручен до тех пор пока не исчезнет.
SCROLL_FLAG_SCROLL : Элемент view будет прокручиваться в направлении события прокрутки.
SCROLL_FLAG_SNAP : В конце прокрутки, если view видим только частично, он будет докручен до его ближайшего края.

CoordinatorLayout Behaviors

Проведем не большой эксперимент, запустим Android Studio (>= 1.4) и создадим проект из шаблона: Scrolling Activity, ничего не изменяя, компилирием и вот что мы видим:

При рассмотрении сгенерированного кода, ни макеты layout ни java классы не имеют ничего относящегося к маштабированию анимации плавающей кнопки при прокрутке. Почему?

Ответ находится в исходном коде FloatingActionButton , с тех пор как Android Studio v1.2 включает java декомпилятор, с помощью ctrl/cmd + click мы можем проверить исходный код и посмотреть что происходит:

За маштабирование анимации отвечает новый элемент, представленый вместе с design library, под названием Behavior . В данном случае , который зависит от некоторых факторов включая прокрутку, показывать FAB или нет, интересно, не правда ли?

SwipeDismissBehavior

Продолжим углубление в код, если вы посмотрите внутрь пакета виджетов design support library, то сможете найти открытй клас под названием: SwipeDismissBehavior . С этим новым Behavior мы можем очень легко реализовать функцию свайп для отмены в наших шаблонах с CoordinatorLayout :

Читайте также:  Android java find view by id

Custom Behaviors

Создать свой шаблон поведения (Behavior) не так и сложно как может показаться, для начала мы должны принять во внимание несколько основных элементов: child и dependency.

Child и dependency

child это элемент который усиливает поведение, dependency — тот кто будет обслуживать его как тригер для взаимодействия с child элементом. Посмотрим на пример, child — элемент ImageView, а dependency это Toolbar, таким образом, если Toolbar движется, ImageView тоже движется.

Теперь, когда мы определили концепт, можем поговорить о реализации, первым шагом будет наследование от:
, значение T будет класс который принадлежит view, что необходим нам для координации, в данном случае ImageView, после чего мы должны переопределить следующие методы:

  • layoutDependsOn
  • onDependentViewChanged

Метод: layoutDependsOn будет вызван каждый раз когда что-то случится в layout, чтобы вернуть true , как только мы определили dependency, в примере, этот метод срабатывает автоматически при прокручивании (т.к. Toolbar будет двигаться), таким образом, мы можем подать знак нашему child отреагировать соответствующим образом.

Всякий раз когда layoutDependsOn возвращает true будет вызван второй onDependentViewChanged . Вот тут-то мы и должны реализовать нашу анимацию, перевод или движения всегда зависят от предоставленной зависимости.

Источник

Android CollapsingToolbarLayout — Material Design Tutorial -2

In this tutorial, we will learn to create a collapsing toolbar layout that was introduced with Design Support library . Before starting anything, let’s check for the new layouts that were introduced with design library :

This is a super powered FrameLayout. We can specify behaviours for child views of coordinatorlayout for various interections.

AppBarLayout should be used as a direct child of coordinatorLayout. Basically, it is a vertical Linear Layout , children of which can manage the behaviour when the content is scrolled. setScrollFlags(int) or app:layout_scrollFlags is used to provide their children their desired scrolling behavior.

This layout is a wrapper for toolbar which implements a collapsing app bar . It is used as a direct child of AppBarLayout.

CollapsingToolbarLayout has the following features :

A Title that is larger when the layout is fully visible and becomes smaller when the layout is scrolled off the screen. setTitle(CharSequence)can be used to set the title .collapsedTextAppearance and expandedTextAppearance attributes are used to change the title appearance.

A full-bleed scrim that will be shown or hidden when the scroll position has hit a certain threshold.We can change it using setContentScrim(Drawable).

Status bar scrim:

A scrim that will be shown or hidden behind the status bar when the scroll position hits a threshold value. setStatusBarScrim(Drawable) can be used to change this. This will work only on lollipop devices.

  1. Create a project on Android Studio with an Activity “ScrollingActivity” and its corresponding layout “activity_scrolling.xml” .

You can see in the activity_scrolling.xml file that CoordinatorLayout is the base layout and AppbarLayout is working as parent layout of CollapsingToolbarLayout.

Also we are using the palette library to change the Content Scrim and StatusBar Scrim color of the collapsing toolbar layout in the ScrollingActivity :

That’s it. Cone this project from github hereand try to run it . If you have any query or if you are having any problem running this project, please comment below.

Источник

Оцените статью