ListView 的 ScrollingViewBehavior
ScrollingViewBehavior for ListView
我有两项活动使用 AppBarLayout
以及来自支持库 22 的 Toolbar
和 TabLayout
。
两者的布局非常相似:一个 Toolbar
在顶部,在它下面 TabLayout
,在它下面是一个包含 3 个 Fragment
的 ViewPager
。
第一个 activity 的 Fragment
有一个 RecyclerView
,
第二个 activity 的 Fragment
正在使用 ListView
。
来自 https://github.com/chrisbanes/cheesesquare 的可滚动 Toolbar
示例在使用 RecyclerView
的第一个 activity 上运行良好,但在 ListView
上运行良好。
我已经尝试创建一个扩展 AppBarLayout.ScrollingViewBehavior
的自定义 ListViewScrollBehavior
,但到目前为止没有成功。
TouchEvent
仅在水平滚动时传递给自定义 class,但在滚动 ListView
(垂直)时不会。
有什么方法可以将 CoordinatorLayout
与 ListView
一起使用吗?
我认为 CoordinatorLayout
仅适用于 RecyclerView
和 NestedScrollView
。尝试将 ListView
包裹在 NestedScrollView
中,或将其转换为 RecyclerView
和 LinearLayoutManager
现在让它工作的唯一解决方案是使用这个:
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
,这样效果会更好。
我有两项活动使用 AppBarLayout
以及来自支持库 22 的 Toolbar
和 TabLayout
。
两者的布局非常相似:一个 Toolbar
在顶部,在它下面 TabLayout
,在它下面是一个包含 3 个 Fragment
的 ViewPager
。
第一个 activity 的 Fragment
有一个 RecyclerView
,
第二个 activity 的 Fragment
正在使用 ListView
。
来自 https://github.com/chrisbanes/cheesesquare 的可滚动 Toolbar
示例在使用 RecyclerView
的第一个 activity 上运行良好,但在 ListView
上运行良好。
我已经尝试创建一个扩展 AppBarLayout.ScrollingViewBehavior
的自定义 ListViewScrollBehavior
,但到目前为止没有成功。
TouchEvent
仅在水平滚动时传递给自定义 class,但在滚动 ListView
(垂直)时不会。
有什么方法可以将 CoordinatorLayout
与 ListView
一起使用吗?
我认为 CoordinatorLayout
仅适用于 RecyclerView
和 NestedScrollView
。尝试将 ListView
包裹在 NestedScrollView
中,或将其转换为 RecyclerView
和 LinearLayoutManager
现在让它工作的唯一解决方案是使用这个:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
listView.setNestedScrollingEnabled(true);
}
它显然只适用于 Lollipop。
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
,这样效果会更好。