今天就跟大家聊聊有關(guān)如何在Android中嵌套滾動(dòng)NestedScroll,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
創(chuàng)新互聯(lián)是專業(yè)的榮成網(wǎng)站建設(shè)公司,榮成接單;提供成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè),網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行榮成網(wǎng)站開發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!
原理
NestedScroll的其實(shí)很簡(jiǎn)單.
一般的觸摸消息的分發(fā)都是從外向內(nèi)的,由外層的ViewGroup的dispatchTouchEvent方法調(diào)用到內(nèi)層的View的dispatchTouchEvent方法.
而NestedScroll提供了一個(gè)反向的機(jī)制,內(nèi)層的view在接收到ACTION_MOVE的時(shí)候,將滾動(dòng)消息先傳回給外層的ViewGroup,看外層的ViewGroup是不是需要消耗一部分的移動(dòng),然后內(nèi)層的View再去消耗剩下的移動(dòng).內(nèi)層view可以消耗剩下的滾動(dòng)的一部分,如果還沒有消耗完,外層的view可以再選擇把最后剩下的滾動(dòng)消耗掉.
上面的描述可能有點(diǎn)繞,可以看下面的圖來(lái)幫助理解:
具體實(shí)現(xiàn)
NestedScroll機(jī)制會(huì)涉及到四個(gè)類:
NestedScrollingChild, NestedScrollingChildHelper 和 NestedScrollingParent , NestedScrollingParentHelper
NestedScrollingChild和NestedScrollingParent是兩個(gè)接口,我們先看看他們的聲明:
public interface NestedScrollingChild { public void setNestedScrollingEnabled(boolean enabled); public boolean isNestedScrollingEnabled(); public boolean startNestedScroll(int axes); public void stopNestedScroll(); public boolean hasNestedScrollingParent(); public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow); public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow); public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed); public boolean dispatchNestedPreFling(float velocityX, float velocityY); } public interface NestedScrollingParent { public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes); public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes); public void onStopNestedScroll(View target); public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed); public void onNestedPreScroll(View target, int dx, int dy, int[] consumed); public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed); public boolean onNestedPreFling(View target, float velocityX, float velocityY); public int getNestedScrollAxes(); }
這里真正重要的其實(shí)是NestedScrollingParent的幾個(gè)方法,因?yàn)槠渌椒ǘ寄苤苯幼孨estedScrollingChildHelper或者NestedScrollingParentHelper去代理:
onStartNestedScroll 是否接受嵌套滾動(dòng),只有它返回true,后面的其他方法才會(huì)被調(diào)用
onNestedPreScroll 在內(nèi)層view處理滾動(dòng)事件前先被調(diào)用,可以讓外層view先消耗部分滾動(dòng)
onNestedScroll 在內(nèi)層view將剩下的滾動(dòng)消耗完之后調(diào)用,可以在這里處理最后剩下的滾動(dòng)
onNestedPreFling 在內(nèi)層view的Fling事件處理之前被調(diào)用
onNestedFling 在內(nèi)層view的Fling事件處理完之后調(diào)用
我們只要讓子view和父view分別實(shí)現(xiàn)NestedScrollingChild和NestedScrollingParent接口,然后分別調(diào)用NestedScrollingChildHelper和NestedScrollingParentHelper的對(duì)應(yīng)方法去代理一些具體功能,然后在NestedScrollingChild的onTouchEvent那里根據(jù)需求調(diào)用startNestedScroll/dispatchNestedPreScroll/stopNestedScroll就能實(shí)現(xiàn)嵌套滾動(dòng)了:
//NestedScrollingChild private NestedScrollingChildHelper mHelper = new NestedScrollingChildHelper(this); public boolean startNestedScroll(int axes) { return mHelper.startNestedScroll(axes); } public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) { return mHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow); } ...
//NestedScrollingParent private NestedScrollingParentHelper mHelper = new NestedScrollingParentHelper(this); public void onNestedScrollAccepted(View child, View target, int axes) { mHelper.onNestedScrollAccepted(child, target, axes); } public int getNestedScrollAxes() { return mHelper.getNestedScrollAxes(); } ...
但是如果你使用sdk21及以上的版本,NestedScroll機(jī)制已經(jīng)直接集成到了View中了,你只需要直接重寫View的對(duì)應(yīng)方法就好
布局
我們先看布局文件
<me.linjw.nestedscrolldemo.NestedScrollParentView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <FrameLayout android:id="@+id/header" android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:layout_width="match_parent" android:layout_height="200dp" android:src="@mipmap/ic_launcher" /> </FrameLayout> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorAccent" android:text="Title" android:textAlignment="center" android:textSize="20dp" /> <android.support.v7.widget.RecyclerView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="match_parent" /> </me.linjw.nestedscrolldemo.NestedScrollParentView>
最外層是我們自定義的NestedScrollParentView,其實(shí)它是一個(gè)LinearLayout,內(nèi)部豎直排列了三個(gè)子view:
一個(gè)由FrameLayout包裹的ImageView
一個(gè)TextView
一個(gè)RecyclerView
代碼
為了簡(jiǎn)便起見,我們先直接用sdk22的版本用重寫View方法的方式去實(shí)現(xiàn)它.
NestedScrollParentView中有兩個(gè)方法比較重要,嵌套滾動(dòng)基本上就是由這兩個(gè)方法實(shí)現(xià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 headerScrollUp = dy > 0 && getScrollY() < mHeaderHeight; boolean headerScrollDown = dy < 0 && getScrollY() > 0 && !target.canScrollVertically(-1); if (headerScrollUp || headerScrollDown) { scrollBy(0, dy); consumed[1] = dy; } }
onStartNestedScroll 這個(gè)方法如果返回true的話代表接受由內(nèi)層傳來(lái)的滾動(dòng)消息,我們直接返回true就好,否則后面的消息都接受不到
onNestedPreScroll 這個(gè)方法用于消耗內(nèi)層view的一部分滾動(dòng).我們需要將消耗掉的滾動(dòng)存到counsumed中讓consumed知道.例如我們這里在頂部的FrameLayout需要移動(dòng)的情況下會(huì)消耗掉所有的dy,這樣內(nèi)層的view(即RecyclerView)就不會(huì)滾動(dòng)了.
這里的mHeaderHeight保存的是頂部的FrameLayout的高度:
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mHeaderHeight = mHeader.getMeasuredHeight(); }
Android是一種基于Linux內(nèi)核的自由及開放源代碼的操作系統(tǒng),主要使用于移動(dòng)設(shè)備,如智能手機(jī)和平板電腦,由美國(guó)Google公司和開放手機(jī)聯(lián)盟領(lǐng)導(dǎo)及開發(fā)。
看完上述內(nèi)容,你們對(duì)如何在Android中嵌套滾動(dòng)NestedScroll有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。
本文標(biāo)題:如何在Android中嵌套滾動(dòng)NestedScroll
文章網(wǎng)址:http://vcdvsql.cn/article8/pejsip.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供移動(dòng)網(wǎng)站建設(shè)、微信公眾號(hào)、企業(yè)建站、網(wǎng)站收錄、網(wǎng)站制作、軟件開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)