標(biāo)簽(空格分隔): android
NestedScrolling(ns)是一種嵌套滑動機制,能夠互相協(xié)同處理事件。
在5.0版本中view已經(jīng)實現(xiàn)了ns,為了兼容提供了NestedScrollingChild,NestedScrollingParent接口。并且提供了NestedScrollingChildHelper,NestedScrollingParentHelper輔助我們實現(xiàn)ns。 
NestedScrollingChildHelper源碼分析
//開始nestedscrolling(ns)public boolean startNestedScroll(int axes) { //已經(jīng)啟動就直接返回true if (hasNestedScrollingParent()) { // Already in PRogress return true; } //如果是可以嵌套滑動的 if (isNestedScrollingEnabled()) { ViewParent p = mView.getParent(); View child = mView; while (p != null) { //回調(diào)onStartNestedScroll和onNestedScrollAccepted if (ViewParentCompat.onStartNestedScroll(p, child, mView, axes)) { mNestedScrollingParent = p; ViewParentCompat.onNestedScrollAccepted(p, child, mView, axes); return true; } //如果沒有同意協(xié)同處理,則父view設(shè)為子view繼續(xù)向上遍歷尋找 if (p instanceof View) { child = (View) p; } p = p.getParent(); } } //到最后都沒找到,返回false,沒有協(xié)同處理者 return false;}//讓協(xié)同處理的父view先處理,然后返回消費信息給target(ns發(fā)起者)public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) { //判斷使能和是否有協(xié)同處理者 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { if (dx != 0 || dy != 0) { int startX = 0; int startY = 0; if (offsetInWindow != null) { //記錄開始處于的窗體位置 mView.getLocationInWindow(offsetInWindow); startX = offsetInWindow[0]; startY = offsetInWindow[1]; } //如果沒有指定輸出,創(chuàng)建臨時的 if (consumed == null) { if (mTempNestedScrollConsumed == null) { mTempNestedScrollConsumed = new int[2]; } consumed = mTempNestedScrollConsumed; } consumed[0] = 0; consumed[1] = 0; //回調(diào)onNestedPreScroll ViewParentCompat.onNestedPreScroll(mNestedScrollingParent, mView, dx, dy, consumed); //計算窗體位置變化 if (offsetInWindow != null) { mView.getLocationInWindow(offsetInWindow); offsetInWindow[0] -= startX; offsetInWindow[1] -= startY; } return consumed[0] != 0 || consumed[1] != 0; } else if (offsetInWindow != null) { offsetInWindow[0] = 0; offsetInWindow[1] = 0; } } //沒有消費 return false;}//target(ns)處理后反饋信息給協(xié)同者public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) { if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) { int startX = 0; int startY = 0; if (offsetInWindow != null) { mView.getLocationInWindow(offsetInWindow); startX = offsetInWindow[0]; startY = offsetInWindow[1]; } //回調(diào)onNestedScroll ViewParentCompat.onNestedScroll(mNestedScrollingParent, mView, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); if (offsetInWindow != null) { mView.getLocationInWindow(offsetInWindow); offsetInWindow[0] -= startX; offsetInWindow[1] -= startY; } return true; } else if (offsetInWindow != null) { // No motion, no dispatch. Keep offsetInWindow up to date. offsetInWindow[0] = 0; offsetInWindow[1] = 0; } } return false;}//fling處理都很簡單,按需回調(diào)public boolean dispatchNestedPreFling(float velocityX, float velocityY) { if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { return ViewParentCompat.onNestedPreFling(mNestedScrollingParent, mView, velocityX, velocityY); } return false;}public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { return ViewParentCompat.onNestedFling(mNestedScrollingParent, mView, velocityX, velocityY, consumed); } return false;}demo
新聞熱點
疑難解答