Android属性动画
2020-04-29 本文已影响0人
Sky_Blue
一、属性动画
- 定义属性
- 提供get set方法
- 使用ObjectAnimator
二、ObjectAnimator 、PropertyValuesHolder 用法
public class CircleView extends View {
private Paint mPaint;
private float radius;
public CircleView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
{
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.RED);
}
public float getRadius() {
return radius;
}
public void setRadius(float radius) {
this.radius = radius;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius, mPaint);
}
}
public class MainActivity extends AppCompatActivity {
private CircleView mCircleView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCircleView = findViewById(R.id.cv);
// 1. 半径从0到50dp
ObjectAnimator animator = ObjectAnimator
.ofFloat(mCircleView,
"radius",
Utils.dip2px(50)
);
animator.setDuration(1500);
animator.setStartDelay(1000);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
// 2. 从左向右移动:中间慢两边快
translate();
}
});
animator.start();
}
private void translate() {
// 2. 从左向右移动:中间慢两边快
int width = ((ViewGroup) mCircleView.getParent()).getWidth()-Utils.dip2px(200);
Keyframe frame1=Keyframe.ofFloat(0.0f,0);
Keyframe frame2=Keyframe.ofFloat(0.1f,0.2f*width);
Keyframe frame3=Keyframe.ofFloat(0.8f,0.6f*width);
Keyframe frame4=Keyframe.ofFloat(0.9f,0.9f*width);
Keyframe frame5=Keyframe.ofFloat(1f,1f*width);
PropertyValuesHolder holder=PropertyValuesHolder.ofKeyframe("translationX",
frame2,frame3,frame1,frame4,frame5);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mCircleView, holder);
animator.setDuration(1500);
animator.start();
}
}
三、TypeEvaluator用法
public class PointView extends View {
private Point point = new Point(0, 0);
private Paint mPaint;
private int radius = Utils.dip2px(25);
public PointView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
{
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.RED);
}
public Point getPoint() {
return point;
}
public void setPoint(Point point) {
this.point = point;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 绘制一个圆:
canvas.drawCircle(point.x + radius, point.y + radius, radius, mPaint);
}
}
public class MainActivity extends AppCompatActivity {
private PointView mPointView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPointView = findViewById(R.id.pv);
// 最终移动的点的位置
Point endPoint = new Point(Utils.dip2px(200), Utils.dip2px(300));
// 动画效果:圆按对角线移动
ObjectAnimator animator = ObjectAnimator.ofObject(mPointView, "point",
new PointTypeEvaluator(), endPoint);
animator.setDuration(2000);
animator.setInterpolator(new DecelerateInterpolator());
animator.setStartDelay(1000);
animator.start();
}
/**
* 自定义TypeEvaluator
*/
static class PointTypeEvaluator implements TypeEvaluator<Point> {
@Override
public Point evaluate(float fraction, Point startValue, Point endValue) {
// 计算下一个点
int x = (int) (startValue.x + (endValue.x - startValue.x) * fraction);
int y = (int) (startValue.y + (endValue.y - startValue.y) * fraction);
return new Point(x, y);
}
}
}
六、综合案例:翻转的View
/**
* 翻转的View
*/
public class FancyFlipView extends View {
private Bitmap mBitmap;
private Paint mPaint;
private Camera mCamera;
private int iconWidth;
private int iconHeight;
private int mStart;
// 顶部翻转角度
private float topFlip=0;
// 底部翻转角度
private float bottomFlip=0;
// 整体旋转角度
private float flipRotation=0;
public FancyFlipView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public static final int ICON_WIDTH = 150;
{
mCamera = new Camera();
mCamera.setLocation(0, 0, Utils.getZForCamera());
mBitmap = Utils.getBitmap(getContext(), R.drawable.icon, Utils.dip2px(ICON_WIDTH));
iconWidth = mBitmap.getWidth();
iconHeight = mBitmap.getHeight();
// 这个值可以随便定
mStart = iconWidth / 2;
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 整体改成左右了
// Camera 三维变换: 倒着写
// 绘制上半部:倒着写
canvas.save();
canvas.translate(iconWidth / 2 + mStart, iconHeight / 2+mStart);
canvas.rotate(-flipRotation);
mCamera.save();
mCamera.rotateY(topFlip);// 底部翻转
mCamera.applyToCanvas(canvas);
mCamera.restore();
canvas.clipRect(-iconWidth , -iconHeight , 0 , iconHeight);
canvas.rotate(flipRotation);
canvas.translate(-(iconWidth / 2 + mStart), -(iconHeight / 2+mStart));
canvas.drawBitmap(mBitmap, mStart, mStart, mPaint);
canvas.restore();
// 绘制下半部:倒着写
// 1. 将图片中心点移动到左上角
// 2. 旋转图片
// 2. 裁剪图片下半部分
// 3. 将图片中心移回去
canvas.save();
canvas.translate(iconWidth / 2 + mStart, iconHeight / 2+mStart);
canvas.rotate(-flipRotation);
mCamera.save();
mCamera.rotateY(bottomFlip);// 底部翻转
mCamera.applyToCanvas(canvas);
mCamera.restore();
canvas.clipRect(0 , -iconHeight, iconWidth , iconHeight );
canvas.rotate(flipRotation);
canvas.translate(-(iconWidth / 2 + mStart), -(iconHeight / 2+mStart));
canvas.drawBitmap(mBitmap, mStart, mStart, mPaint);
canvas.restore();
}
public float getTopFlip() {
return topFlip;
}
public void setTopFlip(float topFlip) {
this.topFlip = topFlip;
invalidate();
}
public float getBottomFlip() {
return bottomFlip;
}
public void setBottomFlip(float bottomFlip) {
this.bottomFlip = bottomFlip;
invalidate();
}
public float getFlipRotation() {
return flipRotation;
}
public void setFlipRotation(float flipRotation) {
this.flipRotation = flipRotation;
invalidate();
}
}
public class MainActivity extends AppCompatActivity {
private FancyFlipView mFlipView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFlipView = findViewById(R.id.pv);
// 右边向中间翻转45度
ObjectAnimator bottomFlip = ObjectAnimator.ofFloat(mFlipView, "bottomFlip", -45);
bottomFlip.setDuration(500);
// 旋转270度:Y 轴和 X轴相当于对换
ObjectAnimator flipRotation = ObjectAnimator.ofFloat(mFlipView, "flipRotation", 270);
flipRotation.setDuration(1500);
// 左边向中间翻转45度(旋转270度后,这条边在上面了)
ObjectAnimator topFlip = ObjectAnimator.ofFloat(mFlipView, "topFlip", 45);
topFlip.setDuration(500);
AnimatorSet set=new AnimatorSet();
set.setStartDelay(500);
// 按顺序执行
set.playSequentially(bottomFlip,flipRotation,topFlip);
set.start();
}
}