android动画效果

须知少年凌云志,曾许人间第一流。这篇文章主要讲述android动画效果相关的知识,希望能为你提供帮助。
http://blog.csdn.net/L_wwbs/article/details/53408830
本篇通过自定义View模拟一个物理现象— — 竖直平面内小球在最低点以一定初速度在重力作用下绕圆环做变速圆周运动的效果(从最低点减速到0时上升到最高点再加速到初始速度时回到最低点)。可以用于加载等待等场景,下面按照自定义View的步骤具体说明一下。
1、定义属性为了能在布局文件中使用我们的自定义控件,定制其属性,我们需要自定义一些控件的属性,以供更灵活的使用此控件。
【android动画效果】 
[java]  view plain  copy  

  1. < ?xml  version="1.0"  encoding="utf-8"?>    
  2. < resources>    
  3.         < attr  name="ringColor"  format="color"> < /attr>    
  4.         < attr  name="ringWidth"  format="dimension"> < /attr>    
  5.         < attr  name="globuleColor"  format="color"> < /attr>    
  6.         < attr  name="globuleRadius"  format="dimension"> < /attr>    
  7.         < attr  name="cycleTime"  format="float"> < /attr>    
  8.         < declare-styleable  name="AccelerateCircularView">    
  9.                 < attr  name="ringColor"  />    
  10.                 < attr  name="ringWidth"  />    
  11.                 < attr  name="globuleColor"  />    
  12.                 < attr  name="globuleRadius"  />    
  13.                 < attr  name="cycleTime"  />    
  14.         < /declare-styleable>    
  15. < /resources>    
  16. 2、获取属性 自定义属性完成后,我们需要在自定义View的构造方法中逐一获取这些属性。[java]  view plain  copy  
    1. public  AccelerateCircularView(Context  context)  {   
    2.               this(context,  null);    
    3.       }   
    4.    
    5.       public  AccelerateCircularView(Context  context,  AttributeSet  attrs)  {   
    6.               this(context,  attrs,  0);    
    7.       }   
    8.    
    9.       public  AccelerateCircularView(Context  context,  AttributeSet  attrs,   
    10.                                                                   int  defStyle)  {   
    11.               super(context,  attrs,  defStyle);    
    12.               TypedArray  attrsArray  =  context.getTheme().obtainStyledAttributes(   
    13.                               attrs,  R.styleable.AccelerateCircularView,  defStyle,  0);    
    14.               mRingColor  =  attrsArray.getColor(   
    15.                               R.styleable.AccelerateCircularView_ringColor,  Color.GRAY);    
    16.               mGlobuleColor  =  attrsArray.getColor(   
    17.                               R.styleable.AccelerateCircularView_globuleColor,  Color.BLUE);    
    18.               mRingWidth  =  attrsArray.getDimension(   
    19.                               R.styleable.AccelerateCircularView_ringWidth,  TypedValue   
    20.                                               .applyDimension(TypedValue.COMPLEX_UNIT_DIP,  1,   
    21.                                                               getResources().getDisplayMetrics()));    
    22.               mGlobuleRadius  =  attrsArray.getDimension(   
    23.                               R.styleable.AccelerateCircularView_globuleRadius,  TypedValue   
    24.                                               .applyDimension(TypedValue.COMPLEX_UNIT_DIP,  6,   
    25.                                                               getResources().getDisplayMetrics()));    
    26.               mCycleTime  =  attrsArray.getFloat(   
    27.                               R.styleable.AccelerateCircularView_cycleTime,  3000);    
    28.               attrsArray.recycle();    
    29.               mPaint  =  new  Paint();    
    30.    
    31.       }   
    这里要注意通过attrsArray.recycle()及时回收TypedArray ,避免浪费内存资源  。
    2、重写onMeasure[java]  view plain  copy  
    1. @Override   
    2.         protected  void  onMeasure(int  widthMeasureSpec,  int  heightMeasureSpec)  {   
    3.                 int  mWidth  ,  mHeight  ;    
    4.                 int  widthMode  =  MeasureSpec.getMode(widthMeasureSpec);    
    5.                 int  widthSize  =  MeasureSpec.getSize(widthMeasureSpec);    
    6.                 int  heightMode  =  MeasureSpec.getMode(heightMeasureSpec);    
    7.                 int  heightSize  =  MeasureSpec.getSize(heightMeasureSpec);    
    8.                 if  (widthMode  ==  MeasureSpec.EXACTLY)  {   
    9.                         mWidth  =  widthSize;    
    10.                 }  else  {   
    11.                         mWidth  =  169;    
    12.                         if  (widthMode  ==  MeasureSpec.AT_MOST)  {   
    13.                                 mWidth  =  Math.min(mWidth,  widthSize);    
    14.                         }   
    15.    
    16.                 }   
    17.                 if  (heightMode  ==  MeasureSpec.EXACTLY)  {   
    18.                         mHeight  =  heightSize;    
    19.                 }  else  {   
    20.                         mHeight  =  169;    
    21.                         if  (heightMode  ==  MeasureSpec.AT_MOST)  {   
    22.                                 mHeight  =  Math.min(mWidth,  heightSize);    
    23.                         }   
    24.    
    25.                 }   
    26.    
    27.                 setMeasuredDimension(mWidth,  mHeight);    
    28.    
    29.         }   

    这里主要是处理当VIew设置为“ wrap_content” 时需要自己给出测量结果,否则系统默认给我们测量的结果将是"match_parent"的大小。3、重写onDraw[java]  view plain  copy  
    1. @Override   
    2.       protected  void  onDraw(Canvas  canvas)  {   
    3.               super.onDraw(canvas);    
    4.    
    5.               int  central  =  Math.min(getWidth(),  getHeight())  /  2;    
    6.    
    7.               mRingRadius  =  central  -  mGlobuleRadius;    
    8.    
    9.               if  (mGlobuleRadius  <   mRingWidth  /  2)  {//  小球嵌在环里   
    10.                       mRingRadius  =  central  -  mRingWidth  /  2;    
    11.               }   
    12.               mPaint.setStrokeWidth(mRingWidth);    
    13.               mPaint.setStyle(Style.STROKE);    
    14.               mPaint.setAntiAlias(true);    
    15.               mPaint.setColor(mRingColor);    
    16.               canvas.drawCircle(central,  central,  mRingRadius,  mPaint); //  绘制圆环   
    17.               mPaint.setStyle(Style.FILL);    
    18.               mPaint.setAntiAlias(true);    
    19.               mPaint.setColor(mGlobuleColor);    
    20.    
    21.               if  (currentAngle  ==  -1)  {   
    22.                       startCirMotion();    
    23.               }   
    24.               drawGlobule(canvas,  central); //  绘制小球   
    25.       }   
    [java]  view plain  copy  
    1. /** 
    2.       *  绘制小球,起始位置为圆环最低点 
    3.       * 
    4.       *  @param  canvas 
    5.       *  @param  central 
    6.       */   
    7.     private  void  drawGlobule(Canvas  canvas,  float  central)  {   
    8.    
    9.             float  cx  =  central  +  (float)  (mRingRadius  *  Math.cos(currentAngle));    
    10.             float  cy  =  (float)  (central  +  mRingRadius  *  Math.sin(currentAngle));    
    11.             canvas.drawCircle(cx,  cy,  mGlobuleRadius,  mPaint);    
    12.    
    13.     }   
    这里完成对控件的绘制,这里根据圆环半径、当前旋转的角度结合三角函数关系来定位小球的当前坐标。其中对小球速度的控制是通过属性动画获取当前旋转角度实现。4、定义动画[java]  view plain  copy  
    1. /** 
    2.         *  旋转小球 
    3.         */   
    4.       private  void  startCirMotion()  {   
    5.               ValueAnimator  animator  =  ValueAnimator.ofFloat(90f,  450f); //起始位置在最低点   
    6.               animator.setDuration((long)  mCycleTime).setRepeatCount(   
    7.                               ValueAnimator.INFINITE);    
    8.               animator.addUpdateListener(new  AnimatorUpdateListener()  {   
    9.                       @Override   
    10.                       public  void  onAnimationUpdate(ValueAnimator  animation)  {   
    11.                               Float  angle  =  (Float)  animation.getAnimatedValue();    
    12.                               currentAngle  =  angle  *  Math.PI  /  180;    
    13.                               invalidate();    
    14.                       }   
    15.               });    
    16.               //  animator.setInterpolator(new  LinearInterpolator()); //  匀速旋转   
    17.               //  自定义开始减速到0后加速到初始值的Interpolator   
    18.               animator.setInterpolator(new  TimeInterpolator()  {   
    19.    
    20.                       @Override   
    21.                       public  float  getInterpolation(float  input)  {   
    22.                               float  output;    
    23.                               if  (input  <   0.5)  {   
    24.                                       output  =  (float)  Math.sin(input  *  Math.PI)  /  2; //  先加速   
    25.                               }  else  {   
    26.                                       output  =  1  -  (float)  Math.sin(input  *  Math.PI)  /  2; //  后减速,最高点(中间)速度为0   
    27.                               }   
    28.                               return  output;    
    29.                       }   
    30.               });    
    31.               animator.start();    
    32.       }   

    这里通过自定义Interpolator来实现对动画进度变化快慢的控制,动画设置的值为小球的当前角度。初值90° 保证小球从最低点开始运动。 http://blog.csdn.net/chjr1000/article/details/41823505

    推荐阅读