NestedScrollingParent接口提供了八個(gè)接口,按照順序大致可以這么來記:
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();
如果不使用系統(tǒng)提供的CoordinatorLayout以及AppbarLayout窝撵,那么該怎么實(shí)現(xiàn)頭部懸停View呢豌汇?
NestedScrollingParent與NestedScrollingChild接口配合使用就能達(dá)到想要的效果郎楼。由于系統(tǒng)提供的諸如NestedScrollView岔霸,RecyclerView等都實(shí)現(xiàn)了NestedScrollingChild接口褒繁,因此我們只需要實(shí)現(xiàn)一個(gè)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());
}
因?yàn)镸ySimpleStickyLayout如果不重新測量的話钠导,那么他的高度就只有屏幕的高度震嫉,而當(dāng)我們向上滑動(dòng)時(shí),底部就會(huì)出現(xiàn)空白沒有展示View的區(qū)域牡属。為了將該區(qū)域進(jìn)行繪制票堵,因此進(jìn)行了重新測量。
二:重寫接口
@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是因?yàn)樾枰?dāng)前View進(jìn)行攔截逮栅。在onNestedPreScroll()中進(jìn)行了是否消費(fèi)的計(jì)算悴势。其中mScrollY如果為正值,則表示向上移動(dòng)措伐,mScrollX為正值特纤,則表示向左移動(dòng)。dy為正值侥加,也表示向上移動(dòng)捧存。
三:邊界檢查
@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);
}
}
內(nèi)容參考:鴻洋的博客