ListView 的 ScrollingViewBehavior

ScrollingViewBehavior for ListView

我有两项活动使用 AppBarLayout 以及来自支持库 22 的 ToolbarTabLayout

两者的布局非常相似:一个 Toolbar 在顶部,在它下面 TabLayout,在它下面是一个包含 3 个 FragmentViewPager

第一个 activity 的 Fragment 有一个 RecyclerView, 第二个 activity 的 Fragment 正在使用 ListView

来自 https://github.com/chrisbanes/cheesesquare 的可滚动 Toolbar 示例在使用 RecyclerView 的第一个 activity 上运行良好,但在 ListView 上运行良好。

我已经尝试创建一个扩展 AppBarLayout.ScrollingViewBehavior 的自定义 ListViewScrollBehavior,但到目前为止没有成功。 TouchEvent 仅在水平滚动时传递给自定义 class,但在滚动 ListView(垂直)时不会。

有什么方法可以将 CoordinatorLayoutListView 一起使用吗?

我认为 CoordinatorLayout 仅适用于 RecyclerViewNestedScrollView。尝试将 ListView 包裹在 NestedScrollView 中,或将其转换为 RecyclerViewLinearLayoutManager

现在让它工作的唯一解决方案是使用这个:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
     listView.setNestedScrollingEnabled(true);
}

它显​​然只适用于 Lollipop。

is to use ViewCompat.setNestedScrollingEnabled(View, boolean)

的替代解决方案
ViewCompat.setNestedScrollingEnabled(listView, true);

当然,嵌套滚动行为仅适用于 Lollipop。

为了能够在 AppBarLayout 上做出反应的视图,它需要实现 NestedScrollingChild。列表视图不是。但它可以由委托 class 轻松实现。使用它,它会像 RecyclerView 那样做

public class NestedScrollingListView extends ListView implements NestedScrollingChild {
private NestedScrollingChildHelper mNestedScrollingChildHelper;

public NestedScrollingListView(final Context context) {
    super(context);
    initHelper();
}

public NestedScrollingListView(final Context context, final AttributeSet attrs) {
    super(context, attrs);
    initHelper();
}

public NestedScrollingListView(final Context context, final AttributeSet attrs, final int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    initHelper();
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public NestedScrollingListView(final Context context, final AttributeSet attrs, final int defStyleAttr, final int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    initHelper();
}

private void initHelper() {
    mNestedScrollingChildHelper = new NestedScrollingChildHelper(this);
    setNestedScrollingEnabled(true);
}

@Override
public void setNestedScrollingEnabled(final boolean enabled) {
    mNestedScrollingChildHelper.setNestedScrollingEnabled(enabled);
}

@Override
public boolean isNestedScrollingEnabled() {
    return mNestedScrollingChildHelper.isNestedScrollingEnabled();
}

@Override
public boolean startNestedScroll(final int axes) {
    return mNestedScrollingChildHelper.startNestedScroll(axes);
}

@Override
public void stopNestedScroll() {
    mNestedScrollingChildHelper.stopNestedScroll();
}

@Override
public boolean hasNestedScrollingParent() {
    return mNestedScrollingChildHelper.hasNestedScrollingParent();
}

@Override
public boolean dispatchNestedScroll(final int dxConsumed, final int dyConsumed, final int dxUnconsumed, final int dyUnconsumed, final int[] offsetInWindow) {
    return mNestedScrollingChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow);
}

@Override
public boolean dispatchNestedPreScroll(final int dx, final int dy, final int[] consumed, final int[] offsetInWindow) {
    return mNestedScrollingChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
}

@Override
public boolean dispatchNestedFling(final float velocityX, final float velocityY, final boolean consumed) {
    return mNestedScrollingChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
}

@Override
public boolean dispatchNestedPreFling(final float velocityX, final float velocityY) {
    return mNestedScrollingChildHelper.dispatchNestedPreFling(velocityX, velocityY);
}

}

ListView ScrollingViewBehavior 只支持 >= 21.

否则你应该按照下面的方式编写代码:

private int mPreviousVisibleItem;


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    listView.setNestedScrollingEnabled(true);
} else {
    listView.setOnScrollListener(new AbsListView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
        }
        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            if (firstVisibleItem > mPreviousVisibleItem) {
                appBarLayout.setExpanded(false, true);
            } else if (firstVisibleItem < mPreviousVisibleItem) {
                appBarLayout.setExpanded(true, true);
            }
            mPreviousVisibleItem = firstVisibleItem;
        }
    });
}

您可以添加

    android:nestedScrollingEnabled="true"

从XML到ListView,请注意,这只支持API 21+。或者,您可以将 ListView 换成 RecyclerView,这样效果会更好。