Android 自定义动画&Camera 3D动画

原创
2014/12/17 23:35
阅读数 6.4K

1.相关知识点

对于Androi的帧动画,可以制作gif图片,有时为了能够动态的生成帧动画,就得需要使用代码构建了

  • AnimationDrawable类中使用 addFrame用来添加帧。
  • AnimationDrawable类中使用 start来启动动画。
  • AnimationDrawable类中使用 stop来停止动画。

 

  1. 当移动位置不是相对于ParentView或者Window时,补间动画只实现了View图像位置的改变,但控件并没有发生位移

    说明:当属性动画移动后,如果不会到原来的位置,那么点击新的位置,将接受不到Click事件,点击原来的位置可以接收到点击事件

  2. 补间动画通过不断的调用OnDraw方法来进行UI的绘制,而属性动画一般只调用ViewGroup进行绘制

  3. 属性动画不会主动恢复到原来的状态,而是一直保持新的状态,直到下一次改变

  4. 属性动画可以使用playToggther,play..with,play...[width]... after,playSequentaily进行动画的控制,使用起来非常方便

  5. 属性动画可以通过ObjectAnimator和PropertyValueHolder进行动态控制,增加了动画的灵活性

 

2.pivot:X和piovtY中心点

中心点对所有动画属性都起作用,scale(参见QQ侧滑),translate,rotate

中心点描述了动画的发展方向

 

另外对于补间动画的理解中容易出现错误的地方,更正如下:

RotateAnimation ra = new RotateAnimation(fromDegrees, toDegrees, pivotX, pivotY)

pivotX,pivotY当数值大于1时表示的是实际像素

RotateAnimation ra = new RotateAnimation(fromDegrees, toDegrees, pivotXType, pivotXValue, pivotYType, pivotYValue)

pivotX,pivotY当数值大于1时表示的是比例位置

 

3.Animation自定义动画

3.1继承Animation自定义动画

public class CustomAnimation extends Animation {

	@Override
	protected void applyTransformation(float interpolatedTime, Transformation t) {
		super.applyTransformation(interpolatedTime, t);
		t.getMatrix().setTranslate((float) (Math.sin(10*interpolatedTime)*50), 0);
	}
	
	
}

3.2使用ValueAnimator结合监听器自定义动画

final ShapeHolder ball5 = balls.get(4);

ValueAnimator valueAnimator5 = ValueAnimator.ofFloat(0f, getHeight() - ball5.getHeight());
valueAnimator5.setDuration(500);
valueAnimator5.addUpdateListener(new AnimatorUpdateListener() {                    
                // ValueAnimator需要自己在监听处理中设置对象参数                    
                @Override                    
                public void onAnimationUpdate(ValueAnimator animation) {                        
              // 用animation.getAnimatedValue()得到当前的属性值,设置进动画对象中                        
                ball5.setY((Float) animation.getAnimatedValue());                        
                // 记得要刷新View否则不会调用重新绘制                        
                invalidate();
          }

});
valueAnimator5.start();

3.3使用TypeEvaluator自定义动画

public class Point {

    private float x;

    private float y;

    public Point(float x, float y) {
        this.x = x;
        this.y = y;
    }
    
    public void setX(float x){
       this.x = x
    }
      public void setY(float y){
       this.y = y;
    }

    public float getX() {
        return x;
    }

    public float getY() {
        return y;
    }

}
public class PointEvaluator implements TypeEvaluator{

    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        Point startPoint = (Point) startValue;
        Point endPoint = (Point) endValue;
        float x = startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX());
        float y = startPoint.getY() + fraction * (endPoint.getY() - startPoint.getY());
        Point point = new Point(x, y);
        return point;
    }

}
public class MyTaget{
  private Point point = new Point(0f,0f);
  public void setPoint(Point p){
    this.point = point;
  }
  public Point getPoint(){
    return this.point;
  }
}

Point point1 = new Point(0, 0);
Point point2 = new Point(300, 300);
ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), point1, point2);
anim.setTarget(new MyTarget());
anim.setDuration(5000);
anim.start();

或如下使用

ObjectAnimator.ofObject(Object target, String propertyName, TypeEvaluator evaluator, Object... values)

4.扩展对象属性动画

建立一个类似Serializable的接口标记

public interface IWrapperAnimator {
}

(由于属性动画的属性必须具有setter与getter,对于一些特别的属性,需要使用代理)

public class WrapperView implements IWrapperAnimator {
   private View targetView;
    public WrapperView(View targetView){
      this.targetView = targetView;
   }
   public void setWidth(int width){
   targetView.getLayoutParams().width = width;
    targetView.requestLayout();
  }
   public int getWidth(){
   return targetView.getLayoutParams().width;
  }
}

使用方法

WrapperView wrapper = new WrapperView(mLinearLayout);
ObjectAnimator.ofInt(wrapper,"width",300).setDuration(3000).start();

注意:属性动画驱动是通过反射的方式来实现的,因此混淆的时候需要注意混淆文件配置

-keepclassmembers public class * implements com.m8.qq.ui.IWrapperAnimator{
    *** set*(***);
    *** get*();
}

5.Camera动画

Android 自定义动画Animation 使用Camera实现3D动画效果,这里的Camera不是相机,而是场景动画,意味着有导演

public class MyAnimation extends Animation {
 int mCenterX,mCenterY;
 
 Camera camera = new Camera();
 
 public MyAnimation() {
 }
 @Override
 protected void applyTransformation(float interpolatedTime, Transformation t) {
  Matrix matrix = t.getMatrix();  
  camera.save();
  camera.translate(0f, 0f, (1300 - 1300*interpolatedTime));
  camera.rotateY(360*interpolatedTime);
  camera.getMatrix(matrix);
  matrix.preTranslate(-mCenterX, -mCenterY);
  matrix.postTranslate(mCenterX,mCenterY);
  camera.restore();
 }
 @Override
 public void initialize(int width, int height, int parentWidth,
   int parentHeight) {
  super.initialize(width, height, parentWidth, parentHeight);
  //初始化中间坐标
  mCenterX = width/2;
  mCenterY = height/2;
  
  setDuration(2000);
  setFillAfter(true);
  setInterpolator(new LinearInterpolator());
 }
}

 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
7 收藏
0
分享
返回顶部
顶部