问题
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