CoordinatorLayout,NestedScrollView,AppbarLayout源码解析

NestedScrollView.java

1.触摸事件

1 @Override 2 public boolean onTouchEvent(MotionEvent ev) { 3 initVelocityTrackerIfNotExists(); 4 5 MotionEvent vtev = MotionEvent.obtain(ev); 6 7 final int actionMasked = MotionEventCompat.getActionMasked(ev); 8 9 if (actionMasked == MotionEvent.ACTION_DOWN) { 10 mNestedYOffset = 0; 11 } 12 vtev.offsetLocation(0, mNestedYOffset); 13 14 switch (actionMasked) { 15 case MotionEvent.ACTION_DOWN: { 16 //通知nested开始滚动 17 startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL); 18 break; 19 } 20 case MotionEvent.ACTION_MOVE: 21 //通知nested滚动 22 if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) { 23 deltaY -= mScrollConsumed[1]; 24 vtev.offsetLocation(0, mScrollOffset[1]); 25 mNestedYOffset += mScrollOffset[1]; 26 } 27 ... 28 if (mIsBeingDragged) { 29 // Scroll to follow the motion event 30 ... 31 if (dispatchNestedScroll(0, scrolledDeltaY, 0, unconsumedY, mScrollOffset)) { 32 mLastMotionY -= mScrollOffset[1]; 33 vtev.offsetLocation(0, mScrollOffset[1]); 34 mNestedYOffset += mScrollOffset[1]; 35 } else if (canOverscroll) { 36 ... 37 } 38 } 39 break; 40 case MotionEvent.ACTION_CANCEL: 41 case MotionEvent.ACTION_UP: 42 /* Release the drag */ 43 mIsBeingDragged = false; 44 mActivePointerId = INVALID_POINTER; 45 recycleVelocityTracker(); 46 if (mScroller.springBack(getScrollX(), getScrollY(), 0, 0, 0, getScrollRange())) { 47 ViewCompat.postInvalidateOnAnimation(this); 48 } 49 //通知nested滚动 50 stopNestedScroll(); 51 break; 52 53 } 54 55 if (mVelocityTracker != null) { 56 mVelocityTracker.addMovement(vtev); 57 } 58 vtev.recycle(); 59 return true; 60 }

分析dispatchNestedScroll方法

1@Override 2 public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, 3 int dyUnconsumed, int[] offsetInWindow) { 4 return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, 5 offsetInWindow); 6 } 7 8 9NestedScrollViewHelper 10public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, 11 int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) { 12 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 13 if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) { 14 int startX = 0; 15 int startY = 0; 16 if (offsetInWindow != null) { 17 mView.getLocationInWindow(offsetInWindow); 18 startX = offsetInWindow[0]; 19 startY = offsetInWindow[1]; 20 } 21//调用控制器的onNestedScroll 22 ViewParentCompat.onNestedScroll(mNestedScrollingParent, mView, dxConsumed, 23 dyConsumed, dxUnconsumed, dyUnconsumed); 24 25 if (offsetInWindow != null) { 26 mView.getLocationInWindow(offsetInWindow); 27 offsetInWindow[0] -= startX; 28 offsetInWindow[1] -= startY; 29 } 30 return true; 31 } else if (offsetInWindow != null) { 32 // No motion, no dispatch. Keep offsetInWindow up to date. 33 offsetInWindow[0] = 0; 34 offsetInWindow[1] = 0; 35 } 36 } 37 return false; 38 } 39 40ViewParentCompatLollipop.java 41public static void onNestedScroll(ViewParent parent, View target, int dxConsumed, 42 int dyConsumed, int dxUnconsumed, int dyUnconsumed) { 43 try { 44 parent.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); 45 } catch (AbstractMethodError e) { 46 Log.e(TAG, "ViewParent " + parent + " does not implement interface " + 47 "method onNestedScroll", e); 48 } 49 }

CoordinatorLayout.java

1 public void onNestedScroll(View target, int dxConsumed, int dyConsumed, 2 int dxUnconsumed, int dyUnconsumed) { 3 final int childCount = getChildCount(); 4 boolean accepted = false; 5 6 for (int i = 0; i < childCount; i++) { 7 final View view = getChildAt(i); 8 final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 9//判断子View是否支持NestedScroll 10 if (!lp.isNestedScrollAccepted()) { 11 continue; 12 } 13 14 final Behavior viewBehavior = lp.getBehavior(); 15 if (viewBehavior != null) { 16//调用Behavior.onNestedScroll,设置子View的偏移量 17 viewBehavior.onNestedScroll(this, view, target, dxConsumed, dyConsumed, 18 dxUnconsumed, dyUnconsumed); 19 accepted = true; 20 } 21 } 22 23 if (accepted) { 24//通知布局变话 25 dispatchOnDependentViewChanged(true); 26 } 27 }

AppbarLayout#Behavior

1@Override 2 public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, 3 View target, int dxConsumed, int dyConsumed, 4 int dxUnconsumed, int dyUnconsumed) { 5 if (dyUnconsumed < 0) { 6 // If the scrolling view is scrolling down but not consuming, it's probably be at 7 // the top of it's content 8//向下滚动时,调整View位置 9 scroll(coordinatorLayout, child, dyUnconsumed, 10 -child.getDownNestedScrollRange(), 0); 11 // Set the expanding flag so that onNestedPreScroll doesn't handle any events 12 mSkipNestedPreScroll = true; 13 } else { 14 // As we're no longer handling nested scrolls, reset the skip flag 15 mSkipNestedPreScroll = false; 16 } 17 } 18 19HeaderBehavior.java 20//设置偏移量 21final int scroll(CoordinatorLayout coordinatorLayout, V header, 22 int dy, int minOffset, int maxOffset) { 23 return setHeaderTopBottomOffset(coordinatorLayout, header, 24 getTopBottomOffsetForScrollingSibling() - dy, minOffset, maxOffset); 25 } 26 27 28 int setHeaderTopBottomOffset(CoordinatorLayout parent, V header, int newOffset, 29 int minOffset, int maxOffset) { 30 final int curOffset = getTopAndBottomOffset(); 31 int consumed = 0; 32 33 if (minOffset != 0 && curOffset >= minOffset && curOffset <= maxOffset) { 34 // If we have some scrolling range, and we're currently within the min and max 35 // offsets, calculate a new offset 36 newOffset = MathUtils.constrain(newOffset, minOffset, maxOffset); 37//计算有效偏移量,如果偏移量有变化则设置新的偏移量 38 if (curOffset != newOffset) { 39 setTopAndBottomOffset(newOffset); 40 // Update how much dy we have consumed 41 consumed = curOffset - newOffset; 42 } 43 } 44 45 return consumed; 46 } 47 48public boolean setTopAndBottomOffset(int offset) { 49 if (mViewOffsetHelper != null) { 50 return mViewOffsetHelper.setTopAndBottomOffset(offset); 51 } else { 52 mTempTopBottomOffset = offset; 53 } 54 return false; 55 } 56//子View在布局时创建ViewOffsetHelper 57@Override 58 public boolean onLayoutChild(CoordinatorLayout parent, V child, int layoutDirection) { 59 // First let lay the child out 60 layoutChild(parent, child, layoutDirection); 61 62 if (mViewOffsetHelper == null) { 63 mViewOffsetHelper = new ViewOffsetHelper(child); 64 } 65 mViewOffsetHelper.onViewLayout(); 66 67 if (mTempTopBottomOffset != 0) { 68 mViewOffsetHelper.setTopAndBottomOffset(mTempTopBottomOffset); 69 mTempTopBottomOffset = 0; 70 } 71 if (mTempLeftRightOffset != 0) { 72 mViewOffsetHelper.setLeftAndRightOffset(mTempLeftRightOffset); 73 mTempLeftRightOffset = 0; 74 } 75 76 return true; 77 }
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

CoordinatorLayout,NestedScrollView,AppbarLayout源码解析 - HelloWorld