NestedScrollingParent接口提供了八个接口,按照顺序大致可以这么来记:
start-->accepted-->preScroll-->scroll-->preFling-->fling-->stop
boolean onStartNestedScroll( View child, View target, int axes);
void onNestedScrollAccepted( View child, View target, int axes);
void onNestedPreScroll(View target, int dx, int dy, int[] consumed);
void onNestedScroll( View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed);
boolean onNestedPreFling(View target, float velocityX, float velocityY);
boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed);
void onStopNestedScroll( View target);
int getNestedScrollAxes();
如果不使用系统提供的CoordinatorLayout以及AppbarLayout,那么该怎么实现头部悬停View呢?
NestedScrollingParent与NestedScrollingChild接口配合使用就能达到想要的效果。由于系统提供的诸如NestedScrollView,RecyclerView等都实现了NestedScrollingChild接口,因此我们只需要实现一个NestedScrollingParent接口,来配合NestedScrollView来使用就可以了。
先看一下布局
<com.goodsnow.view.custom.nestedscroll.MySimpleStickyLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:ignore="MissingDefaultResource">
<TextView
android:textColor="#ffffff"
android:textSize="50dp"
android:gravity="center"
android:id="@+id/tvTop"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@color/colorAccent"
android:text="Top" />
<TextView
android:id="@+id/tvMiddle"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/colorPrimary"
android:gravity="center"
android:text="stickyHeady"
android:textColor="@android:color/white"
android:textSize="20dp" />
<androidx.core.widget.NestedScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:gravity="center"
android:text="scrollView"
android:textColor="@android:color/white"
android:textSize="40dp"
android:layout_width="match_parent"
android:layout_height="800dp"
android:background="@color/design_default_color_error" />
<TextView
android:gravity="center"
android:text="scrollView"
android:textColor="@android:color/white"
android:textSize="40dp"
android:layout_width="match_parent"
android:layout_height="800dp"
android:background="@color/design_default_color_primary" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</com.goodsnow.view.custom.nestedscroll.MySimpleStickyLayout>
对于MySimpleStickyLayout的代码来说,主要分为三部分。第一部分是测量,第二部分是重写接口,第三部分检测边界。
一:测量
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mTop = findViewById(R.id.tvTop);
mMiddle = findViewById(R.id.tvMiddle);
mBottom = findViewById(R.id.scrollView);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
ViewGroup.LayoutParams layoutParams = mBottom.getLayoutParams();
layoutParams.height = getMeasuredHeight() - mMiddle.getMeasuredHeight();
setMeasuredDimension(getMeasuredWidth(), mTop.getMeasuredHeight() + mMiddle.getMeasuredHeight() + mBottom.getMeasuredHeight());
}
因为MySimpleStickyLayout如果不重新测量的话,那么他的高度就只有屏幕的高度,而当我们向上滑动时,底部就会出现空白没有展示View的区域。为了将该区域进行绘制,因此进行了重新测量。
二:重写接口
@Override
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
return true;
}
@Override
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
super.onNestedPreScroll(target, dx, dy, consumed);
boolean hide = dy >= 0 && getScrollY() < mTop.getHeight();
boolean show = dy <= 0 && getScrollY() >= 0&& !ViewCompat.canScrollVertically(target, -1);
if (hide || show) {
scrollBy(0, dy);
consumed[1] = dy;
}
}
onStartNestedScroll()返回true是因为需要当前View进行拦截。在onNestedPreScroll()中进行了是否消费的计算。其中mScrollY如果为正值,则表示向上移动,mScrollX为正值,则表示向左移动。dy为正值,也表示向上移动。
三:边界检查
@Override
public void scrollTo(int x, int y) {
if(y<0){
y=0;
}
if(y>mTop.getMeasuredHeight()){
y=mTop.getMeasuredHeight();
}
if(y!=getScrollY()){
super.scrollTo(x, y);
}
}
内容参考:鸿洋的博客