Based on my reading so far, Behavior
can only be applied to direct children of CoordinatorLayout
. But the following code is confusing me:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".ScrollingActivity">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/app_bar_height"
android:fitsSystemWindows="true"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="@android:color/holo_red_light"
app:layout_scrollFlags="scroll"
app:toolbarId="@+id/toolbar">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="parallax"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.NestedScrollView
android:id="@+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".ScrollingActivity"
tools:showIn="@layout/activity_scrolling">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin"
android:text="@string/large_text" />
</android.support.v4.widget.NestedScrollView>
</FrameLayout>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test Button"
android:visibility="visible"
android:layout_gravity="bottom"
app:layout_anchor="@id/nestedScrollView"
app:layout_behavior="am.i.coord.CustomBehavior"
/>
</android.support.design.widget.CoordinatorLayout>
The NestedScrollView
is not a direct child of CoordinatorLayout
(being wrapped in a FrameLayout), but still has a Behavior
applied, which is properly triggering changes in AppBarLayout.
The Button
I added at the same level with a custom behavior
is working only if I make it a direct child of CoordinatorLayout
. If I move it inside the FrameLayout
as a sibling of NestedScrollView
, then none of the callbacks are executed.
Why this difference? If Behavior
is not meant to be used by CoordinatorLayout's
non-direct children, is there another way for the non-direct children to be notified on scroll changes in NestedScrollView
? I can only think of adding a dummy view to the CoordinatorLayout
which will emit scroll events to indirect children, but it makes the code messy.
CoordinatorLayout is a super-powered FrameLayout . CoordinatorLayout is intended for two primary use cases: As a top-level application decor or chrome layout. As a container for a specific interaction with one or more child views.
You can set the behavior on an instance of CoordinatorLayout. LayoutParams with setBehavior method. To get a proper Behavior object that represents the same thing as @string/appbar_scrolling_view_behavior you should create an instance of AppBarLayout. ScrollingViewBehavior .
CoordinatorLayout is a super-powered FrameLayout. At the Google I/O 2015, Google introduced Coordinator Layout to remove the difficulties of having more than one layouts in FrameLayout. Now, with the help of the CoordinatorLayout, the interaction between the views become very easy even in the case of animation.
Android CoordinatorLayout is a super-powered FrameLayout. It has a lot more to offer than it seems. It has additional level of control over it's child views. It coordinates the animations and transitions of child views with one another.
Yes, behaviors must be attached to the direct children of a CoordinatorLayout
. Why it works for NestedScrollView
is detailed in the Intercepting everything with CoordinatorLayout blog post, which states:
Nested scrolling can originate not only on direct children of a CoordinatorLayout, but on any child View (a child of a child of a child of a CoordinatorLayout, for example)
This is a separate property of nested scrolling itself, not something unique to CoordinatorLayout
: nested scrolling events propagate up the view hierarchy through each parent ViewGroup
. This is how CoordinatorLayout
gains access to those events and Behaviors are what allows CoordinatorLayout
to dispatch those events to other children not directly in the view hierarchy of the scrolling view.
As you surmised, if you want an indirect child to be aware of scroll changes, you must have a direct child of CoordinatorLayout
, even if it is a dummy view. You can, of course, create a subclass of CoordinatorLayout
and hook into the same event stream if you want as all of the methods can be overridden.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With