【问题标题】:AppBarLayout child doesn't collapse when scrolling滚动时 AppBarLayout 子项不会折叠
【发布时间】:2015-09-15 17:15:37
【问题描述】:

我有一个AppBarLayout,它的子级中包含一个水平的RecyclerViewAppBarLayout 的兄弟是ViewPager(其中包含一个垂直的RecyclerView)。

这是 XML:

<android.support.design.widget.CoordinatorLayout
    android:id="@+id/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"
    tools:context=".ui.search.SearchResultFragment">

<android.support.v4.view.ViewPager
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:overScrollMode="never"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

<android.support.design.widget.AppBarLayout
    android:id="@+id/appBarLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:elevation="@dimen/d2"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <LinearLayout
        android:id="@+id/header_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:background="@color/white"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/back_image_view"
            android:layout_width="?attr/actionBarSize"
            android:layout_height="?attr/actionBarSize"
            android:scaleType="center"
            android:src="@drawable/ic_backarrow_gray"/>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/query_terms_recycler_view"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_gravity="center_vertical"
            android:layout_weight="1"/>

        <ImageView
            android:id="@+id/search_image_view"
            android:layout_width="?attr/actionBarSize"
            android:layout_height="?attr/actionBarSize"
            android:scaleType="center"
            android:src="@drawable/ic_search_gray"/>

    </LinearLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/related_terms_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/search_term_bg"
        app:layout_scrollFlags="scroll|enterAlways"/>

    <android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="@dimen/d8"
        android:background="@color/tab_and_nav_bar"/>

</android.support.design.widget.AppBarLayout>

</android.support.design.widget.CoordinatorLayout>

我已经有了另一个带有 AppBarLayout 的 UI,它能够使用 Toolbar 成功响应滚动。代码几乎相同,但在这种情况下出现了问题,因为 RecyclerView 没有折叠/隐藏。

【问题讨论】:

  • 您的具体问题是什么?
  • 它只是不响应滚动手势。它应该隐藏回收站视图,但没有任何反应。
  • 我相信“可滚动”(可隐藏)视图必须位于顶部。如果您将 RecyclerView LinearLayout 之前移动,它会起作用吗?
  • 我的意思是AppBarLayout的内容应该是 1. RecyclerView (with scrollFlags); 2 线性布局; 3.标签布局。是这样的吗?
  • 嘿,我正在尝试。我会在下面回复你的回答。

标签: android android-support-library android-design-library android-appbarlayout


【解决方案1】:
  • AppBarLayout 只是一个垂直的LinearLayout,所以订单很重要;
  • 让孩子对滚动手势做出反应实际上是通过android:layout_scrollFlags 属性定义scroll 标志。

从该标志的official documentation 中,我们可以读取该标志

视图的滚动与滚动事件直接相关。这面旗帜 需要设置任何其他标志才能生效。如果有的话 在这个之前的兄弟视图没有这个标志,那么这个值 没有效果。

这意味着您的标志被忽略,因为其他孩子没有任何标志。我相信这背后的原因是我们只想隐藏 top 视图 - 如果上面还有东西,底部视图就不会消失。

因此,在这种情况下(您可能不喜欢)的解决方案是:

  • 将该视图移到顶部,这样它将是唯一退出的视图;
  • 为所有视图提供scroll 标志。它们会一起对滚动手势做出反应,这可能不是您想要的。

    <AppBarLayout>
        <RecyclerView ...
            android:layout_scrollFlags="scroll|enterAlways"/>
    
        <LinearLayout ... >
        <TabLayout ... >
    </AppBarLayout>
    

【讨论】:

  • 它几乎可以工作了,谢谢:) 我将RecyclerView 移到了顶部。我让其他孩子没有任何scrollFlags。结果与预期的一样:RecylerView 滚动出来,其他的保持可见。唯一的问题是,按照设计,RecyclerView 应该保持在LinearLayoutTabLayout 之间:(有什么想法吗?
  • 也许也让 LinearLayout 滚动?
  • 是的,它肯定会起作用,但重点是:如果我想要这样的布局怎么办?我的意思是顶部线性布局、回收器视图和选项卡布局,我只需要回收器视图来响应滚动事件?我想这种方法不允许我创建这种布局。你怎么看?
  • 那你用AppBarLayout就不行了。想到的解决方案是为该 RecyclerView 定义一个自定义 Behavior 并覆盖 onNestedScroll()。在那里,当用户向下滚动时,您使 RV 不可见 (setVisibility(View.GONE));向上滚动时,它会再次可见 (setVisibility(View.VISIBLE))。如果您确实需要,请尝试搜索“自定义行为”示例。
  • 谢谢伙计。我自定义了行为,但我以另一种方式做到了:)
【解决方案2】:

非常感谢 @m vai 的提示

我通过自定义AppBarLayout 的行为解决了这个问题 代码如下:

private void setAppBarLayoutBehaviour() {
    AppBarLayout.Behavior behavior = new AppBarLayout.Behavior() {

        @Override
        public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) {
            // Trigger the following events if it is a vertical scrolling
            return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
        }

        @Override
        public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
            super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);

            // If I slowly reach the top, without fling, show the RecyclerView
            int[] firstVisiblePositions = ((StaggeredGridLayoutManager) ((RecyclerView) target).getLayoutManager()).findFirstCompletelyVisibleItemPositions(null);
            for (int position : firstVisiblePositions) {
                if (position == 0) {
                    showRelatedTerms();
                    break;
                }
            }
        }

        @Override
        public boolean onNestedFling(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, float velocityX, float velocityY, boolean consumed) {
            if (velocityY > 500) {
                // Hide the RecyclerView
            } else if (velocityY < -500) {
                // Show the recyclerView
            }
            return true;
        }
    };
    ((CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams()).setBehavior(behavior);
}

而且我没有在 XML 中应用任何 scrollFlags

【讨论】:

    猜你喜欢
    • 2017-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多