当NestedScrollView为空时,停止AppBarLayout在屏幕外滚动 [英] Stop AppBarLayout scrolling off screen when NestedScrollView is empty

查看:62
本文介绍了当NestedScrollView为空时,停止AppBarLayout在屏幕外滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用CoordinatorLayout,AppBarLayout,SwipeRefreshLayout和RecyclerView具有相当典型的List功能-

当RecyclerView具有足够的内容来滚动时,页面看起来很好.但是,当RecyclerView为空或没有足够的内容滚动时,行为是带有app:layout_scrollFlags="scroll|enterAlwaysCollapsed"的AppBarLayout子级将继续滚动-看起来很奇怪.

是否可以在NestedScrollView为空时停止AppBarLayout子级滚动?

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/coordinatorLayout"
        android:background="@android:color/transparent"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/transparent"
            android:elevation="4dp">

            <LinearLayout
                android:id="@+id/eventHeader"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="16dp"
                android:background="@color/green"
                android:orientation="horizontal"
                app:layout_scrollFlags="scroll|enterAlwaysCollapsed">

                <View
                    android:layout_width="0dp"
                    android:layout_height="0dp"
                    android:layout_weight="1"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="scroll|enterAlwaysCollapsed"
                    android:textColor="@color/white"
                    android:textSize="15sp"/>

                <View
                    android:layout_width="0dp"
                    android:layout_height="0dp"
                    android:layout_weight="1"/>

            </LinearLayout>

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

        <android.support.v4.widget.SwipeRefreshLayout
            android:id="@+id/swipeToRefresh"
            android:layout_width="match_parent"
            android:layout_gravity="fill_vertical"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/recyclerView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@android:color/transparent"
                android:dividerHeight="0dp"
                android:layout_gravity="fill_vertical"
                android:drawSelectorOnTop="true"
                android:listSelector="@drawable/selector_ripple_grey_transparent"
                android:scrollbars="vertical"/>

        </android.support.v4.widget.SwipeRefreshLayout>

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

    <TextView
        android:id="@+id/noData"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:padding="16dp"
        android:text="@string/no_data_available"
        android:textSize="17sp"/>

</FrameLayout>

解决方案

不确定该解决方案有多优雅,但是我覆盖了onStartNestedScroll()事件,仅在NestedScrollView可滚动(在这种情况下为RecyclerView)时触发/p>

在onCreate()中:

CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
layoutParams.setBehavior(new AppBarLayoutNoEmptyScrollBehavior(mAppBarLayout, mRecyclerView));

行为:

public class AppBarLayoutNoEmptyScrollBehavior extends AppBarLayout.Behavior {

    AppBarLayout mAppBarLayout;
    RecyclerView mRecyclerView;
    public AppBarLayoutNoEmptyScrollBehavior(AppBarLayout appBarLayout, RecyclerView recyclerView) {
        mAppBarLayout = appBarLayout;
        mRecyclerView = recyclerView;
    }

    public boolean isRecylerViewScrollable(RecyclerView recyclerView) {
        int recyclerViewHeight = recyclerView.getHeight(); // Height includes RecyclerView plus AppBarLayout at same level
        int appCompatHeight    = mAppBarLayout != null ? mAppBarLayout.getHeight() : 0;
        recyclerViewHeight -= appCompatHeight;

        return recyclerView.computeVerticalScrollRange() > recyclerViewHeight;
    }

    @Override
    public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) {
        if (isRecylerViewScrollable(mRecyclerView)) {
            return super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes);
        }
        return false;
    }

}

编辑

作为RecyclerView编辑的解决方案将高度设置为 visible RecyclerView高度和AppBarLayout高度(即CoordinatorLayout高度).

但是,如果您的滚动手势从可见的AppBarLayout区域开始,即使您也将此行为添加到AppBarLayout,也会进行静止滚动.因此,此答案不能解决问题.

I have a fairly typical List functionality using a CoordinatorLayout, AppBarLayout, SwipeRefreshLayout and RecyclerView -

When the RecyclerView has enough content to scroll, the page seems fine. When the RecyclerView is empty or doesn't have enough content to scroll however, the behavior is that the AppBarLayout children with app:layout_scrollFlags="scroll|enterAlwaysCollapsed" will continue to scroll - which looks odd.

Is there a way to stop the AppBarLayout children scrolling when the NestedScrollView is empty?

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/coordinatorLayout"
        android:background="@android:color/transparent"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/transparent"
            android:elevation="4dp">

            <LinearLayout
                android:id="@+id/eventHeader"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="16dp"
                android:background="@color/green"
                android:orientation="horizontal"
                app:layout_scrollFlags="scroll|enterAlwaysCollapsed">

                <View
                    android:layout_width="0dp"
                    android:layout_height="0dp"
                    android:layout_weight="1"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="scroll|enterAlwaysCollapsed"
                    android:textColor="@color/white"
                    android:textSize="15sp"/>

                <View
                    android:layout_width="0dp"
                    android:layout_height="0dp"
                    android:layout_weight="1"/>

            </LinearLayout>

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

        <android.support.v4.widget.SwipeRefreshLayout
            android:id="@+id/swipeToRefresh"
            android:layout_width="match_parent"
            android:layout_gravity="fill_vertical"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/recyclerView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@android:color/transparent"
                android:dividerHeight="0dp"
                android:layout_gravity="fill_vertical"
                android:drawSelectorOnTop="true"
                android:listSelector="@drawable/selector_ripple_grey_transparent"
                android:scrollbars="vertical"/>

        </android.support.v4.widget.SwipeRefreshLayout>

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

    <TextView
        android:id="@+id/noData"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:padding="16dp"
        android:text="@string/no_data_available"
        android:textSize="17sp"/>

</FrameLayout>

解决方案

Not sure how elegant a solution this is but, I overrode the onStartNestedScroll() event to only fire if the NestedScrollView is scrollable (In this case a RecyclerView)

in onCreate():

CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
layoutParams.setBehavior(new AppBarLayoutNoEmptyScrollBehavior(mAppBarLayout, mRecyclerView));

Behavior:

public class AppBarLayoutNoEmptyScrollBehavior extends AppBarLayout.Behavior {

    AppBarLayout mAppBarLayout;
    RecyclerView mRecyclerView;
    public AppBarLayoutNoEmptyScrollBehavior(AppBarLayout appBarLayout, RecyclerView recyclerView) {
        mAppBarLayout = appBarLayout;
        mRecyclerView = recyclerView;
    }

    public boolean isRecylerViewScrollable(RecyclerView recyclerView) {
        int recyclerViewHeight = recyclerView.getHeight(); // Height includes RecyclerView plus AppBarLayout at same level
        int appCompatHeight    = mAppBarLayout != null ? mAppBarLayout.getHeight() : 0;
        recyclerViewHeight -= appCompatHeight;

        return recyclerView.computeVerticalScrollRange() > recyclerViewHeight;
    }

    @Override
    public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) {
        if (isRecylerViewScrollable(mRecyclerView)) {
            return super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes);
        }
        return false;
    }

}

EDIT

Edited solution as RecyclerView gives height as visible RecyclerView height and AppBarLayout height (which is the CoordinatorLayout height).

However, if your scroll gesture starts on the visible AppBarLayout area, a scroll will still take place, even if you add this Behavior to the AppBarLayout as well. This answer therefore is not a fix for the problem.

这篇关于当NestedScrollView为空时,停止AppBarLayout在屏幕外滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆