日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網營銷解決方案
Android嵌套滑動機制NestedScrolling

這篇文章本來打算寫在簡書上的,但是由于頁面不能富文本和markdown同時支持,看到Gemini大神的文章中酷炫、賞心悅目的效果后果斷放棄簡書,看文章本來就會枯燥,如果再沒有美觀的效果,那豈不是要邊看邊睡? 互聯(lián)網給了我們這么多選擇,那我肯定選擇體驗最棒的。

創(chuàng)新互聯(lián)公司長期為1000+客戶提供的網站建設服務,團隊從業(yè)經驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網生態(tài)環(huán)境。為浮梁企業(yè)提供專業(yè)的成都網站制作、成都網站設計、外貿營銷網站建設,浮梁網站改版等技術服務。擁有10年豐富建站經驗和眾多成功案例,為您定制開發(fā)。

具體效果可以對比一下: 

   

說到Gemini,我也是這兩天因為了解NestedScrolling時接觸到的,粗略看了一下資料和文章瀏覽數,贊! 我的大神!

好,前番就到這了,開始正題NestedScrolling。

之前了解NestedScrolling的時候看過一些博客,其中就包括Gemini的segmentfault,當時看的時候因為不仔細不以為然,***才發(fā)現(xiàn)這篇博客是對NestedScrolling介紹最清楚的,作為懲罰也好膜拜也罷,把本來可以cv過來的博客手動敲一遍,順便補充一下自己的一些額外理解。

再次感謝Gemini 

Android 在發(fā)布 Lillipop 版本后,為了更好的用戶體驗,Google為Android的滑動機制提供了NestedScrolling機制。

NestedScrolling的特性可以體現(xiàn)在哪兒呢?

比如你用了Toolbar,下面一個ScrollView,向上滾動隱藏Toolbar,向下滾動顯示Toolbar,這里在邏輯上就是一個NestedScrolling——因為你在滾動整個Toolbar在內的View的過程中,又嵌套滾動了里邊的ScrollView。

如圖:   

在這之前,我們知道Android對Touch事件分發(fā)是有自己的一套機制。主要是有三個函數:

dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent。

這種分發(fā)機制有一個漏洞:

如果子view獲得處理touch事件機會的時候,父view就再也沒有機會處理此次touch事件,直到下一次手指觸發(fā)。

也就是說,我們在滑動子view的時候,如果子view對這個滑動事件不需要處理的時候,只能拋棄這個touch事件,而不會傳給父view去處理。

但Google新的NestedScrolling機制就很好的解決了這個問題。

NestedScrolling主要有四個類需要關注:

  • NestedScrollingChild
  • NestedScrollingChildHelper
  • NestedScrollingParent
  • NestedScrollingParentHelper

以上四個類都在support-v4包中提供,Lollipop中部分View默認實現(xiàn)了NestedScrollingChild或NestedScrollingParent。

v4包中NestedScrollView同時實現(xiàn)了NestedScrollingChild和NestedScrollingParent。

一般實現(xiàn)NestedScrollingChild就可以了,父View用support-design提供的實現(xiàn)了NestedScrollingParent的CoordinatorLayout即可。

 
 
 
 
  1. @Override 
  2.     public void setNestedScrollingEnabled(boolean enabled) { 
  3.         super.setNestedScrollingEnabled(enabled); 
  4.         mChildHelper.setNestedScrollingEnabled(enabled); 
  5.     } 
  6.  
  7.     @Override 
  8.     public boolean isNestedScrollingEnabled() { 
  9.         return mChildHelper.isNestedScrollingEnabled(); 
  10.     } 
  11.  
  12.     @Override 
  13.     public boolean startNestedScroll(int axes) { 
  14.         return mChildHelper.startNestedScroll(axes); 
  15.     } 
  16.  
  17.     @Override 
  18.     public void stopNestedScroll() { 
  19.         mChildHelper.stopNestedScroll(); 
  20.     } 
  21.  
  22.     @Override 
  23.     public boolean hasNestedScrollingParent() { 
  24.         return mChildHelper.hasNestedScrollingParent(); 
  25.     } 
  26.  
  27.     @Override 
  28.     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) { 
  29.         return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow); 
  30.     } 
  31.  
  32.     @Override 
  33.     public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) { 
  34.         return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow); 
  35.     } 
  36.  
  37.     @Override 
  38.     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { 
  39.         return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed); 
  40.     } 
  41.  
  42.     @Override 
  43.     public boolean dispatchNestedPreFling(float velocityX, float velocityY) { 
  44.         return mChildHelper.dispatchNestedPreFling(velocityX, velocityY); 
  45.     } 

 

簡單邏輯這樣就可以實現(xiàn)嵌套滑動。

以上接口都是業(yè)務邏輯中自己調用,NestedScrollingChildHelper是如何實現(xiàn)的呢? 先看一下startNestedScroll方法

 
 
 
 
  1. /** 
  2.      * Start a new nested scroll for this view. 
  3.      * 
  4.      * 

    This is a delegate method. Call it from your {@link android.view.View View} subclass 

  5.      * method/{@link NestedScrollingChild} interface method with the same signature to implement 
  6.      * the standard policy.

     
  7.      * 
  8.      * @param axes Supported nested scroll axes. 
  9.      *             See {@link NestedScrollingChild#startNestedScroll(int)}. 
  10.      * @return true if a cooperating parent view was found and nested scrolling started successfully 
  11.      */ 
  12.     public boolean startNestedScroll(int axes) { 
  13.         if (hasNestedScrollingParent()) { 
  14.             // Already in progress 
  15.             return true; 
  16.         } 
  17.         if (isNestedScrollingEnabled()) { 
  18.             ViewParent p = mView.getParent(); 
  19.             View child = mView; 
  20.             while (p != null) { 
  21.                 if (ViewParentCompat.onStartNestedScroll(p, child, mView, axes)) { 
  22.                     mNestedScrollingParent = p; 
  23.                     ViewParentCompat.onNestedScrollAccepted(p, child, mView, axes); 
  24.                     return true; 
  25.                 } 
  26.                 if (p instanceof View) { 
  27.                     child = (View) p; 
  28.                 } 
  29.                 p = p.getParent(); 
  30.             } 
  31.         } 
  32.         return false; 
  33.     } 

 

可以看到這里是幫你實現(xiàn)了與NestedScrollingParent交互的一些方法。

ViewParentCompat是一個和父View交互的兼容類,判斷API version,如果在Lollipop上就調用View自帶的方法,否則判斷如果實現(xiàn)了NestedScrollingParent,則調用實現(xiàn)接口的方法。

子View與父View的交互流程如下:

一、startNestedScroll

首先子View需要開啟整個流程(通過屏幕滑動觸發(fā)touch事件),通過NestedScrollingChildHelper找到并通知實現(xiàn)了NestedScrollingParent的父View中onStartNestedScroll和onNestedScrollAccepted方法。

二、dispatchNestedPreScroll

在子View的onIterceptTouchEvent和onTouch中(一般在MontionEvent.ACTION_MOVE事件里),調用改方法通知父View的滑動距離,該方法的第三第四個參數返回父View消費掉的scroll長度和子View的窗口偏移量,如果這個scroll沒有被消費完,則子View處理剩余距離,由于窗口被移動,如果記錄了手指***的位置,需要根據第四個參數offsetInWindow計算偏移量,才能保證下一次touch事件的計算是正確的。

如果父View接受了滾動參數并部分消費,則該函數返回true,否則返回false。該函數一般在子View處理Scroll前調用。

三、dispatchNestedScroll

向父View匯報滾動情況,包括子View已消費和未消費的值。

如果父View接受了滾動參數,部分消費則函數返回true,否則返回false。

該函數一般在子View處理Scroll后調用。

四、stopNestedScroll

結束整個嵌套滑動流程。

流程中NestedScrollingChild和NestedScrollingParent對應如下:

NestedScrollingChildImplNestedScrollingParentImpl
onStartNestedScrollonStartNestedScrollonNestedScrollAccepted
dispatchNestedPreScrollonNestedPreScroll
dispatchNestedScrollonNestedScroll
stopNestedScrollonStopNestedScroll

一般是子View發(fā)起調用,父View接受回調。

需要關注dispatchNestedPreScroll中的consumed參數:

 
 
 
 
  1. public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) ; 

該參數是一個int類型的數組,長度為2,***個元素是父View消費的x軸方向的滾動距離,第二個元素是父View消費的y軸方向的滾動距離,如果兩個值均不為0,則表示父View已消費滾動距離,則需要對子View滾動距離進行修正,正因為有該參數,使得處理滾動事件時思路更加清晰,不會像以前一樣被一堆滾動參數搞混。

自己理解的NestedScrolling簡要流程圖(不包含F(xiàn)ling事件及返回值的邏輯):


分享題目:Android嵌套滑動機制NestedScrolling
當前地址:http://www.dlmjj.cn/article/dheoiod.html