Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can CoordinatorLayout Behavior be applied only on direct children of CoordinatorLayout?

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.

like image 257
dev Avatar asked Jul 19 '18 23:07

dev


People also ask

What is CoordinatorLayout used for?

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.

How do you set layout behavior programmatically?

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 .

How do you use coordinate layout?

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.

Why we use coordinate layout in Android?

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.


1 Answers

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.

like image 150
ianhanniballake Avatar answered Oct 15 '22 11:10

ianhanniballake