首先来看我门要做的效果:
布局是用一个linerLayout实现NestedScrollingParent 接口,然后里面一次放了一个head,tablayout,viewpager,recyclerview。
NestedScrolling提供了一套父 View 和子 View 滑动交互机制。要完成这样的交互,父 View 需要实现 NestedScrollingParent 接口,而子 View 需要实现 NestedScrollingChild 接口。
@Override
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
return true;
}
private boolean once=true;
@Override
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
boolean hiddenTop = dy > 0 && getScrollY() < 780;
boolean showTop = dy < 0 && getScrollY() > 0 && !ViewCompat.canScrollVertically(target, -1);
if(hiddenTop && once){
ViewGroup.LayoutParams layoutParams = getLayoutParams();
layoutParams.height = getHeight()+780;
setLayoutParams(layoutParams);
requestLayout();
once = false;
}
if (hiddenTop || showTop)
{
Log.i("way","scrolly"+getScrollY());
scrollBy(0, dy);
consumed[1] = dy;
consumed[0] = dx;
}
}
在onStartNestedScroll返回true,这样父view就可以和子view就可以一起配合处理滑动事件。
具体怎么处理在onNestedPreScroll方法中写,hiddenTop 和showTop 分别表示上滑掩藏head和下滑显示head的时候,ViewCompat.canScrollVertically(target, -1)在这里表示下滑的时候recyclerview是否滑动最顶部。如果是上滑掩藏head过程或者
下滑显示head的时候把滑动事件交给父view处理然后通过scrollby滑动父view。第一次上滑由于父view布局是填充整个窗口,所以会导致父view整体上移下面留出空白,所以在第一次上滑的时候应该增加父view的高度,代码中的780是head的高度。
@Override
public void scrollTo(int x, int y)
{
if (y < 0)
{
y = 0;
}
if (y > 780)
{
y = 780;
}
Log.i("way",y+"--"+getScrollY());
if (y != getScrollY())
{
super.scrollTo(x, y);
}
}
最后还要重写scrollTo方法避免滑动过快导致出现空白。
由于recyclerview本身实现了NestedScrollingChild,所以我们可以直接拿来用。如果你想用listview代替recyclerview需要自己实现NestedScrollingChild,在此 listview中需要包含一个 NestedScrollingChildHelper 辅助类。NestedScrollingChild接口的实现,基本上就是调用本 Helper 类的对应的函数即可,因为 Helper 类中已经实现好了 Child 和 Parent 交互的逻辑。