SlidingDrawer源码分析

来源:互联网 发布:宝宝学汉字软件 编辑:程序博客网 时间:2024/06/10 07:16

一属性变量分析

构造函数完成获取attr属性内容的读取,读取用户配置的UI属性,用于构造新的UI结构。

属性内容为,注意这里的SlidingShow作者自己定义的,拷自源码包:

[html] view plaincopy
  1. <resources>  
  2.     <declare-styleable name="SlidingShow">  
  3.         <attr name="handle" format="reference" />  
  4.         <attr name="content" format="reference" />  
  5.         <attr name="orientation"  format="integer" />  
  6.         <attr name="bottomOffset" format="dimension" />  
  7.         <attr name="topOffset" format="dimension" />  
  8.         <attr name="allowSingleTap" format="boolean" />  
  9.         <attr name="animateOnClick" format="boolean" />  
  10.     </declare-styleable>  
  11. </resources>  
android:allowSingleTap:指示是否可以通过handle打开或关闭


android:animateOnClick:指示是否当使用者按下手柄打开/关闭时是否该有一个动画。


android:content:隐藏的内容

android:handle:handle(手柄)

二源码情景分析

在分析源码前,先要选择一个分析顺序,顺序按照ViewGroup绘制周期来进展。


根据viewGroup的绘制顺序开始分析源码。

2.1 测量函数

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @Override  
  2. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {(1)  
  3.     int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);  
  4.     int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);  
  5.   
  6.     int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);  
  7.     int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);  
  8.     final View handle = mHandle;  
  9.     measureChild(handle, widthMeasureSpec, heightMeasureSpec);//(2)获取child View的大小  
  10.     //定义mContent大小  
  11.     if (mVertical) {  
  12.         int height = heightSpecSize - handle.getMeasuredHeight() - mTopOffset;(3)  
  13.         mContent.measure(MeasureSpec.makeMeasureSpec(widthSpecSize, MeasureSpec.EXACTLY),  
  14.                 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));  
  15.     } else {  
  16.         int width = widthSpecSize - handle.getMeasuredWidth() - mTopOffset;  
  17.         mContent.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),  
  18.                 MeasureSpec.makeMeasureSpec(heightSpecSize, MeasureSpec.EXACTLY));  
  19.     }  
  20.     setMeasuredDimension(widthSpecSize, heightSpecSize);  
  21. }  
(1) widthMeasureSpec和heightMeasureSpec为宽度规格和高度规格,可以获取对应的mode(AT_MOST尽大/  EXACTLY精确/  UNSPECIFIED不限制),可以获取对应尺寸。

(2) 获取viewGroup中子视图的尺寸,这里是获取handle的View大小。

(3) 根据对应的偏移量和handle view的大小,设置Content大小。

2.2 视图函数

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @Override  
  2. protected void onLayout(boolean changed, int l, int t, int r, int b) {(1)  
  3.     if (mTracking) {  
  4.         return;  
  5.     }  
  6.     final int width = r - l;    //viewGroup的宽度  
  7.     final int height = b - t;   //viewGroup的高度  
  8.     final View handle = mHandle;  
  9.   
  10.     int childWidth = handle.getMeasuredWidth();     //handle尺寸  
  11.     int childHeight = handle.getMeasuredHeight();  
  12.     int childLeft;  
  13.     int childTop;  
  14.     final View content = mContent;  
  15.     if (mVertical) {  
  16.         childLeft = (width - childWidth) / 2;  
  17.         /**  
  18.          * 设定hanlde位置,这里handle与mBottomOffset和自己大小有关  
  19.          * 设定content位置,这里content与mTopOffset和handle大小有关  
  20.          */  
  21.         childTop = mExpanded ? mTopOffset : height - childHeight + mBottomOffset;(2)  
  22.         //设定content的位置  
  23.         content.layout(0, mTopOffset + childHeight, content.getMeasuredWidth(),  
  24.                 mTopOffset + childHeight + content.getMeasuredHeight());  
  25.     } else {  
  26.         childLeft = mExpanded ? mTopOffset : width - childWidth + mBottomOffset;  
  27.         childTop = (height - childHeight) / 2;  
  28.   
  29.         content.layout(mTopOffset + childWidth, 0,  
  30.                 mTopOffset + childWidth + content.getMeasuredWidth(),  
  31.                 content.getMeasuredHeight());  
  32.     }  
  33.     //确定handle位置  
  34.     handle.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);(3)  
  35.     mHandleHeight = handle.getHeight();  
  36.     mHandleWidth = handle.getWidth();  
  37. }  
(1) 参数changed表示view有新的尺寸或位置;参数l表示相对于父view的Left位置;参数t表示相对于父view的Top位置;参数r表示相对于父view的Right位置;参数b表示相对于父view的Bottom位置。

(2) 问号表达式,根据条件展开或是收缩决定handle的Top位置。

(3) 确定handle位置,包含了展开和收缩的判定,这里Content位置还不太对,还显示在expanded(展开状态)。

2.3 绘制图像函数

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @Override  
  2. protected void dispatchDraw(Canvas canvas) {    //绘制两个子view  
  3.     final long drawingTime = getDrawingTime();  //获取当前GPU绘制view时间,不是日期时间(1)  
  4.     final View handle = mHandle;  
  5.     final boolean isVertical = mVertical;  
  6.   
  7.     drawChild(canvas, handle, drawingTime);(1)  
  8.     if (mTracking || mAnimating) {      //判断当前状态是否为追踪或者发生动画状态  
  9.         final Bitmap cache = mContent.getDrawingCache();  
  10.         if (cache != null) {  
  11.             if (isVertical) {  
  12.                 canvas.drawBitmap(cache, 0, handle.getBottom(), null);  
  13.             } else {  
  14.                 canvas.drawBitmap(cache, handle.getRight(), 0, null);  
  15.             }  
  16.         } else {  
  17.             canvas.save();  
  18.             canvas.translate(isVertical ? 0 : handle.getLeft() - mTopOffset,  
  19.                     isVertical ? handle.getTop() - mTopOffset : 0);(2)  
  20.             drawChild(canvas, mContent, drawingTime);  
  21.             canvas.restore();   //更改save方法前所有的绘制修改  
  22.         }  
  23.     } else if (mExpanded) {  
  24.         drawChild(canvas, mContent, drawingTime);(3)  
  25.     }  
  26. }  

(1)根据当前配置的canvas绘制handle

(2)更改相应的canvas配置,用户绘制content

(3)根据当前配置的canvas绘制content

2.4 完成绘制函数

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @Override  
  2. protected void onFinishInflate() {  
  3.     mHandle = findViewById(mHandleId);  
  4.     if (mHandle == null) {  
  5.         throw new IllegalArgumentException("The handle attribute is must refer to an"  
  6.                 + " existing child.");  
  7.     }  
  8.     mHandle.setOnClickListener(new DrawerToggler());//设置单击监听类(1)  
  9.     mContent = findViewById(mContentId);  
  10.     if (mContent == null) {  
  11.         throw new IllegalArgumentException("The content attribute is must refer to an"  
  12.                 + " existing child.");  
  13.     }  
  14.     mContent.setVisibility(View.GONE);  
  15. }  

(1)设置监听类,内部设置相应的点击事件动画。

2.4.1 监听类的解析

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. private class DrawerToggler implements OnClickListener {  
  2.     public void onClick(View v) {  
  3.         if (mLocked) {(1)  
  4.             return;  
  5.         }  
  6.         // mAllowSingleTap isn't relevant here; you're *always*  
  7.         // allowed to open/close the drawer by clicking with the  
  8.         // trackball.  
  9.         //android:allowSingleTap:指示是否可以通过handle打开或关闭  
  10.         //android:animateOnClick:指示是否当使用者按下手柄打开/关闭时是否该有一个动画。  
  11.         if (mAnimateOnClick) {(2)  
  12.             animateToggle();(3)  
  13.         } else {  
  14.             toggle();(4)  
  15.         }  
  16.     }  
  17. }  
(1)判断是否将view锁住,不允许点击。
(2)判断是否使用单击动画,可以不使用,可以使用。
(3)animateToggle()方法,单击后的动画效果
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public void animateToggle() {  
  2.     if (!mExpanded) {  
  3.         animateOpen();  
  4.     } else {  
  5.         animateClose();  
  6.     }  
  7. }  
展开和收缩两种动画效果:
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public void animateOpen() {  
  2.     prepareContent();   //准备content(-1)  
  3.     final OnDrawerScrollListener scrollListener = mOnDrawerScrollListener;  
  4.     if (scrollListener != null) {  
  5.         scrollListener.onScrollStarted();//调用onScrollStarted函数  
  6.     }  
  7.     animateOpen(mVertical ? mHandle.getTop() : mHandle.getLeft());//展开动画(-2)  
  8.     sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);//设定当前的accessibilityEvent  
  9.       
  10.     if (scrollListener != null) {  
  11.         scrollListener.onScrollEnded(); //调用onScrollEnded函数  
  12.     }  
  13. }  
(-1)准备content
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1.     private void prepareContent() {  
  2.         if (mAnimating) {  
  3.             return;  
  4.         }  
  5.   
  6.         // Something changed in the content, we need to honor the layout request  
  7.         // before creating the cached bitmap  
  8.         final View content = mContent;  
  9.         if (content.isLayoutRequested()) {  
  10.             if (mVertical) {  
  11.                 final int childHeight = mHandleHeight;  
  12.                 int height = getBottom() - getTop() - childHeight - mTopOffset;  
  13.                 content.measure(MeasureSpec.makeMeasureSpec(getRight() - getLeft(), MeasureSpec.EXACTLY),  
  14.                         MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));  
  15.                 content.layout(0, mTopOffset + childHeight, content.getMeasuredWidth(),  
  16.                         mTopOffset + childHeight + content.getMeasuredHeight());  
  17.             } else {  
  18.                 final int childWidth = mHandle.getWidth();  
  19.                 int width = getRight() - getLeft() - childWidth - mTopOffset;  
  20.                 content.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),  
  21.                         MeasureSpec.makeMeasureSpec(getBottom() - getTop(), MeasureSpec.EXACTLY));  
  22.                 content.layout(childWidth + mTopOffset, 0,  
  23.                         mTopOffset + childWidth + content.getMeasuredWidth(),  
  24.                         content.getMeasuredHeight());  
  25.             }  
  26.         }  
  27.         // Try only once... we should really loop but it's not a big deal  
  28.         // if the draw was cancelled, it will only be temporary anyway  
  29.         content.getViewTreeObserver().dispatchOnPreDraw();  
  30.         if (!content.isHardwareAccelerated()) content.buildDrawingCache();  
  31.   
  32.         content.setVisibility(View.GONE);  
  33. //        mContent.setVisibility(View.VISIBLE);  
  34.     }  
重新绘制content,设计相应的measure() layout()等方法。 跟onLayout(boolean changed, int l, int t, int r, int b)方法中绘制content相同。

(-2)动画展开aimateOpen(boolean)方法
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. private void animateOpen(int position) {  
  2.     prepareTracking(position);//准备路径  
  3.     performFling(position, -mMaximumAcceleration, true);//执行跳动  
  4. }  

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. private void prepareTracking(int position) {  
  2.     mTracking = true;//设置标志位  
  3.     mVelocityTracker = VelocityTracker.obtain();(--1)  
  4.     boolean opening = !mExpanded;  
  5.     if (opening) {  
  6.         mAnimatedAcceleration = mMaximumAcceleration;   //加速度设定  
  7.         mAnimatedVelocity = mMaximumMajorVelocity;      //最大速度设定  
  8.         mAnimationPosition = mBottomOffset +  
  9.                 (mVertical ? getHeight() - mHandleHeight : getWidth() - mHandleWidth);  
  10.         moveHandle((int) mAnimationPosition);   //移动动画(--2)  
  11.         mAnimating = true;  
  12.         mHandler.removeMessages(MSG_ANIMATE);(--3)  
  13.         long now = SystemClock.uptimeMillis();  
  14.         mAnimationLastTime = now;   //记录时间  
  15.         mCurrentAnimationTime = now + ANIMATION_FRAME_DURATION;  
  16.         mAnimating = true;  
  17.     } else {  
  18.         if (mAnimating) {  
  19.             mAnimating = false;  
  20.             mHandler.removeMessages(MSG_ANIMATE);  
  21.         }  
  22.         moveHandle(position);(--4)  
  23.     }  
  24. }  
(--1) 速度追踪器获取
(--2) 处理移动操作,moveHandle
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. private void moveHandle(int position) {  
  2.     final View handle = mHandle;  
  3.   
  4.     if (mVertical) {  
  5.         if (position == EXPANDED_FULL_OPEN) {//完全展开  
  6.             handle.offsetTopAndBottom(mTopOffset - handle.getTop());//设定水平偏移量  
  7.             invalidate();  
  8.         } else if (position == COLLAPSED_FULL_CLOSED) {//完全关闭  
  9.             handle.offsetTopAndBottom(mBottomOffset + getBottom() - getTop() -  
  10.                     mHandleHeight - handle.getTop());  
  11.             invalidate();  
  12.         } else {  
  13.             final int top = handle.getTop();//中间状态  
  14.             int deltaY = position - top;  
  15.             if (position < mTopOffset) {  
  16.                 deltaY = mTopOffset - top;  
  17.             } else if (deltaY > mBottomOffset + getBottom() - getTop() - mHandleHeight - top) {  
  18.                 deltaY = mBottomOffset + getBottom() - getTop() - mHandleHeight - top;  
  19.             }  
  20.             handle.offsetTopAndBottom(deltaY);  
  21.   
  22.             final Rect frame = mFrame;  
  23.             final Rect region = mInvalidate;  
  24.   
  25.             handle.getHitRect(frame);  
  26.             region.set(frame);  
  27.   
  28.             region.union(frame.left, frame.top - deltaY, frame.right, frame.bottom - deltaY);  
  29.             region.union(0, frame.bottom - deltaY, getWidth(),  
  30.                     frame.bottom - deltaY + mContent.getHeight());  
  31.   
  32.             invalidate(region);  
  33.         }  
  34.     } else {  
  35.         ......  
  36.     }  
  37. }  
(--3) 移除动画消息
(--4) 移动到相应位置

2.4.1总结animateClose();和animateOpen();基本上一样这里就不在描述了。toggle();更是简单了很多,没有对应的动画,这里也不再分析。

2.5 滑动事件处理

        前面的介绍中,首先描绘如何绘制一个View,并给出了绘制顺序;后来设计了相应的点击事件处理,并提供了有动画和无动画两种情况下的处理函数;那么最后则是处理滑动或者多点触控的事件。
这里会用到两个方法,都是viewGroup的方法,分别是onInterceptTouchEvent()和onTouchEvent()方法,执行顺序遵循下面五点:

1. down事件首先会传递到onInterceptTouchEvent()方法
2. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false,那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。
3. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true,那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。
4. 如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一层次的view的onTouchEvent()处理。
5. 如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @Override  
  2. public boolean onInterceptTouchEvent(MotionEvent event) {  
  3.     if (mLocked) {  
  4.         return false;  
  5.     }  
  6.     final int action = event.getAction();  
  7.     float x = event.getX();  
  8.     float y = event.getY();  
  9.   
  10.     final Rect frame = mFrame;  
  11.     final View handle = mHandle;  
  12.   
  13.     handle.getHitRect(frame);//找到控件占据的矩形区域的矩形坐标  
  14.     if (!mTracking && !frame.contains((int) x, (int) y)) {  
  15.         return false;  
  16.     }  
  17.   
  18.     if (action == MotionEvent.ACTION_DOWN) {  
  19.         mTracking = true;//规划路径中  
  20.   
  21.         handle.setPressed(true);  
  22.         // Must be called before prepareTracking()  
  23.         prepareContent();  
  24.   
  25.         // Must be called after prepareContent()  
  26.         if (mOnDrawerScrollListener != null) {  
  27.             mOnDrawerScrollListener.onScrollStarted();  
  28.         }  
  29.   
  30.         if (mVertical) {  
  31.             final int top = mHandle.getTop();  
  32.             mTouchDelta = (int) y - top;  
  33.             prepareTracking(top);//设定当前位置  
  34.         } else {  
  35.             final int left = mHandle.getLeft();  
  36.             mTouchDelta = (int) x - left;  
  37.             prepareTracking(left);  
  38.         }  
  39.         mVelocityTracker.addMovement(event);  
  40.     }  
  41.   
  42.     return true;//返回true,Event交由onTouchEvent处理  
  43. }  

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @Override  
  2. public boolean onTouchEvent(MotionEvent event) {  
  3.     if (mLocked) {  
  4.         return true;  
  5.     }  
  6.   
  7.     if (mTracking) {  
  8.         mVelocityTracker.addMovement(event);  
  9.         final int action = event.getAction();  
  10.         switch (action) {  
  11.             case MotionEvent.ACTION_MOVE://移动操作  
  12.                 moveHandle((int) (mVertical ? event.getY() : event.getX()) - mTouchDelta);  
  13.                 break;  
  14.             case MotionEvent.ACTION_UP:  
  15.             case MotionEvent.ACTION_CANCEL: {  
  16.                 final VelocityTracker velocityTracker = mVelocityTracker;  
  17.                 velocityTracker.computeCurrentVelocity(mVelocityUnits);  
  18.   
  19.                 float yVelocity = velocityTracker.getYVelocity();  
  20.                 float xVelocity = velocityTracker.getXVelocity();//计算路径的点  
  21.                 boolean negative;  
  22.   
  23.                 final boolean vertical = mVertical;  
  24.                 if (vertical) {  
  25.                     negative = yVelocity < 0;  
  26.                     if (xVelocity < 0) {  
  27.                         xVelocity = -xVelocity;  
  28.                     }  
  29.                     if (xVelocity > mMaximumMinorVelocity) {  
  30.                         xVelocity = mMaximumMinorVelocity;  
  31.                     }  
  32.                 } else {  
  33.                     negative = xVelocity < 0;  
  34.                     if (yVelocity < 0) {  
  35.                         yVelocity = -yVelocity;  
  36.                     }  
  37.                     if (yVelocity > mMaximumMinorVelocity) {  
  38.                         yVelocity = mMaximumMinorVelocity;  
  39.                     }  
  40.                 }  
  41.   
  42.                 float velocity = (float) Math.hypot(xVelocity, yVelocity);// sqrt(x2+ y2).  
  43.                 if (negative) {  
  44.                     velocity = -velocity;  
  45.                 }  
  46.   
  47.                 final int top = mHandle.getTop();  
  48.                 final int left = mHandle.getLeft();  
  49.   
  50.                 if (Math.abs(velocity) < mMaximumTapVelocity) {  
  51.                     if (vertical ? (mExpanded && top < mTapThreshold + mTopOffset) ||  
  52.                             (!mExpanded && top > mBottomOffset + getBottom() - getTop() -  
  53.                                     mHandleHeight - mTapThreshold) :  
  54.                             (mExpanded && left < mTapThreshold + mTopOffset) ||  
  55.                                     (!mExpanded && left > mBottomOffset + getRight() - getLeft() -  
  56.                                             mHandleWidth - mTapThreshold)) {  
  57.   
  58.                         if (mAllowSingleTap) {//是否通过点击打开  
  59.                             playSoundEffect(SoundEffectConstants.CLICK);  
  60.   
  61.                             if (mExpanded) {  
  62.                                 animateClose(vertical ? top : left);  
  63.                             } else {  
  64.                                 animateOpen(vertical ? top : left);  
  65.                             }  
  66.                         } else {  
  67.                             performFling(vertical ? top : left, velocity, false);//执行松开手的后面运动(1)  
  68.                         }  
  69.   
  70.                     } else {  
  71.                         performFling(vertical ? top : left, velocity, false);  
  72.                     }  
  73.                 } else {  
  74.                     performFling(vertical ? top : left, velocity, false);  
  75.                 }  
  76.             }  
  77.             break;  
  78.         }  
  79.     }  
  80.   
  81.     return mTracking || mAnimating || super.onTouchEvent(event);  
  82. }  
(1)松开手后的处理函数
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. private void performFling(int position, float velocity, boolean always) {  
  2.         mAnimationPosition = position;  
  3.         mAnimatedVelocity = velocity;   //手势控制速度  
  4.   
  5.         if (mExpanded) {  
  6.             if (always || (velocity > mMaximumMajorVelocity ||  
  7.                     (position > mTopOffset + (mVertical ? mHandleHeight : mHandleWidth) &&  
  8.                             velocity > -mMaximumMajorVelocity))) {  
  9.                 // We are expanded, but they didn't move sufficiently to cause  
  10.                 // us to retract.  Animate back to the expanded position.  
  11.                 mAnimatedAcceleration = mMaximumAcceleration;  
  12.                 if (velocity < 0) {  
  13.                     mAnimatedVelocity = 0;  
  14.                 }  
  15.             } else {  
  16.                 // We are expanded and are now going to animate away.  
  17.                 mAnimatedAcceleration = -mMaximumAcceleration;  
  18.                 if (velocity > 0) {  
  19.                     mAnimatedVelocity = 0;  
  20.                 }  
  21.             }  
  22.         } else {  
  23.             if (!always && (velocity > mMaximumMajorVelocity ||  
  24.                     (position > (mVertical ? getHeight() : getWidth()) / 2 &&  
  25.                             velocity > -mMaximumMajorVelocity))) {  
  26.                 // We are collapsed, and they moved enough to allow us to expand.  
  27.                 mAnimatedAcceleration = mMaximumAcceleration;  
  28.                 if (velocity < 0) {  
  29.                     mAnimatedVelocity = 0;  
  30.                 }  
  31.             } else {  
  32.                 // We are collapsed, but they didn't move sufficiently to cause  
  33.                 // us to retract.  Animate back to the collapsed position.  
  34.                 mAnimatedAcceleration = -mMaximumAcceleration;  
  35.                 if (velocity > 0) {  
  36.                     mAnimatedVelocity = 0;  
  37.                 }  
  38.             }  
  39.         }  
  40.   
  41.         long now = SystemClock.uptimeMillis();  
  42.         mAnimationLastTime = now;  
  43.         mCurrentAnimationTime = now + ANIMATION_FRAME_DURATION;  
  44.         mAnimating = true;  
  45.         mHandler.removeMessages(MSG_ANIMATE);  
  46.         mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE), mCurrentAnimationTime);  
  47.         stopTracking();//结束动画  
  48.     }  
计算接下来运动所需要的参量,发送handler执行后面的动画。

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. private void doAnimation() {  
  2.      if (mAnimating) {  
  3.          incrementAnimation();  
  4.          if (mAnimationPosition >= mBottomOffset + (mVertical ? getHeight() : getWidth()) - 1) {  
  5.              mAnimating = false;  
  6.              closeDrawer();  
  7.          } else if (mAnimationPosition < mTopOffset) {  
  8.              mAnimating = false;  
  9.              openDrawer();  
  10.          } else {  
  11.              moveHandle((int) mAnimationPosition);  
  12.              mCurrentAnimationTime += ANIMATION_FRAME_DURATION;  
  13.              mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE),  
  14.                      mCurrentAnimationTime);//循环消息  
  15.          }  
  16.      }  
  17.  }  
  18.   
  19.  private void incrementAnimation() {  
  20.      long now = SystemClock.uptimeMillis();  
  21.      float t = (now - mAnimationLastTime) / 1000.0f;                   // ms -> s  
  22.      final float position = mAnimationPosition;  
  23.      final float v = mAnimatedVelocity;                                // px/s  
  24.      final float a = mAnimatedAcceleration;                            // px/s/s  
  25.      mAnimationPosition = position + (v * t) + (0.5f * a * t * t);     // px  
  26.      mAnimatedVelocity = v + (a * t);                                  // px/s  
  27.      mAnimationLastTime = now;                                         // ms  
  28.  }  

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. private class SlidingHandler extends Handler {  
  2.     public void handleMessage(Message m) {  
  3.         switch (m.what) {  
  4.             case MSG_ANIMATE:  
  5.                 doAnimation();  
  6.                 break;  
  7.         }  
  8.     }  
  9. }  
0 0
原创粉丝点击