成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Android嵌套滑動機制NestedScrolling

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

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

具體效果可以對比一下: 

   

 

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

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

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

再次感謝Gemini 

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

NestedScrolling的特性可以體現在哪兒呢?

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

如圖:   

 

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

dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent。

這種分發機制有一個漏洞:

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

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

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

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

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

v4包中NestedScrollView同時實現了NestedScrollingChild和NestedScrollingParent。

一般實現NestedScrollingChild就可以了,父View用support-design提供的實現了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.     } 

 

簡單邏輯這樣就可以實現嵌套滑動。

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

  1. /** 
  2.      * Start a new nested scroll for this view
  3.      * 
  4.      * <p>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.</p> 
  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.     } 

 

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

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

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

一、startNestedScroll

首先子View需要開啟整個流程(通過屏幕滑動觸發touch事件),通過NestedScrollingChildHelper找到并通知實現了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對應如下:

NestedScrollingChildImpl NestedScrollingParentImpl
onStartNestedScroll onStartNestedScrollonNestedScrollAccepted
dispatchNestedPreScroll onNestedPreScroll
dispatchNestedScroll onNestedScroll
stopNestedScroll onStopNestedScroll

一般是子View發起調用,父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簡要流程圖(不包含Fling事件及返回值的邏輯):

 

責任編輯:龐桂玉 來源: segmentfault
相關推薦

2022-09-29 08:19:24

數據庫運維D-SMART

2012-01-04 13:19:46

網絡

2017-08-16 10:36:10

JavaScriptNode.js事件驅動

2017-07-20 16:55:56

Android事件響應View源碼分析

2021-08-25 09:49:48

鴻蒙HarmonyOS應用

2021-08-01 23:47:54

通用模型驅動

2017-01-11 19:00:05

Android嵌套滾動移動開發

2015-10-20 15:54:16

android源碼滑動關閉

2011-05-31 11:55:00

Android 消息機制

2023-05-09 08:36:58

DuchesneWindows

2013-05-17 13:47:25

Android開發ScrollViewGridView

2017-02-14 13:08:45

2023-10-08 08:23:44

Android事件邏輯

2014-07-15 10:16:02

AndroidIntent

2013-03-28 09:07:37

Android開發Intent機制

2016-12-08 10:19:18

Android事件分發機制

2010-01-26 14:43:53

Android數據存儲

2013-04-11 12:40:16

Android消息機制

2017-05-15 19:40:40

AndroidIPC機制

2010-01-28 14:57:36

Android滑動手勢
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 先锋资源在线 | 精品不卡 | 成人午夜在线视频 | 亚洲欧美综合精品久久成人 | 韩国精品在线观看 | 北条麻妃视频在线观看 | 日韩av啪啪网站大全免费观看 | 日本免费黄色 | 欧美性久久 | 久久九| 日韩三级免费网站 | 亚洲男女视频在线观看 | 久久成人精品视频 | 成人午夜免费福利视频 | 久久精品国产一区二区电影 | 国产男女视频网站 | 91视频91| 国内精品成人 | 中文字幕亚洲一区二区va在线 | 亚洲成人一区 | 亚洲人人舔人人 | 国产三级一区二区 | 欧美精品网 | 亚洲小视频在线播放 | 成人av观看| 伊人久久免费视频 | 亚洲一区二区三区在线视频 | 中文在线一区二区 | 免费午夜视频 | 日韩免费福利视频 | 亚洲一区二区中文字幕 | 亚洲福利一区 | 国产精品久久久久久久午夜片 | 99精品电影 | 午夜精品福利视频 | 久久在线看 | 在线视频h | www.久久艹 | 青青操91 | 亚洲成人av一区二区 | 视频在线一区二区 |