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

时光总嘲笑我的痴心妄想 提交于 2021-01-27 07:26:37

问题


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.


回答1:


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.



来源:https://stackoverflow.com/questions/51432900/can-coordinatorlayout-behavior-be-applied-only-on-direct-children-of-coordinator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!