前言
属性动画(ValueAnimator)是 Android3.0 版本推出的动画框架,其功能和拓展性都很强。它不仅能实现所有 Tween 动画的功能,还有很强的拓展性,根本原因是属性动画从本质上已经完全摆脱了控件,虽然我们大多数情况下使用属性动画都是给控件做动画,但是属性动画的底层只是一个数值发生器,和控件没有半毛钱关系。
原理在一定时间间隔内,通过不断对值进行改变、不断将该值赋给对象的属性(任意对象的任意属性),从而实现该对象在该属性上的动画效果。
ValueAnimator 类定义:属性动画机制中最核心的一个类。 ValueAnimator类中有3个重要方法:
- ofInt(int values)
- ofFloat(float values)
- ofObject(int values)
1. 效果图
2. 代码
public class MainActivity extends AppCompatActivity {
private Button mButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = findViewById(R.id.button);
ValueAnimator valueAnimator = ValueAnimator.ofInt(mButton.getLayoutParams().width, 500);
valueAnimator.setDuration(2000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animator) {
int currentValue = (Integer) animator.getAnimatedValue();
mButton.getLayoutParams().width = currentValue;
mButton.requestLayout();
}
});
valueAnimator.start();
}
}
ObjectAnimator 类
1. 效果图
2. 代码
public class MainActivity extends AppCompatActivity {
private Button mButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = findViewById(R.id.button);
ObjectAnimator animator = ObjectAnimator.ofFloat(mButton, "rotation", 0f, 360f);
animator.setDuration(5000);
animator.start();
}
}
手势检测(GestureDetector)
实例:轨迹球
- 效果图
在开发 Android 手机应用过程中,可能需要对一些手势作出响应,如:单击、双击、长按、滑动、缩放等。这些都是很常用的手势。
2. 布局文件
3.代码
/**
* Created on 2019/2/12 15:09
* 轨迹球
* @author Scarf Gong
*/
public class FailingBall extends View {
private int mWidth; // 宽度
private int mHeight; // 高度
private float mStartX = 0; // 小方块开始位置X
private float mStartY = 0; // 小方块开始位置Y
private float mEdgeLength = 200; // 边长
private RectF mRect = new RectF(mStartX, mStartY, mStartX + mEdgeLength, mStartY + mEdgeLength);
private float mFixedX = 0; // 修正距离X
private float mFixedY = 0; // 修正距离Y
private Paint mPaint;
private GestureDetector mGestureDetector;
private boolean mCanFail = false; // 是否可以拖动
private float mSpeedX = 0;
private float mSpeedY = 0;
private Boolean mXFixed = false;
private Boolean mYFixed = false;
private Bitmap mBitmap;
public FailingBall(Context context) {
this(context,null);
}
public FailingBall(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public FailingBall(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mGestureDetector = new GestureDetector(context, mSimpleOnGestureListener);
mPaint = new Paint();
mPaint.setColor(Color.BLACK);
mPaint.setAntiAlias(true);
mBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.ball);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
mStartX = (w - mEdgeLength) / 2;
mStartY = (h - mEdgeLength) / 2;
refreshRectByCurrentPoint();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawOval(mRect, mPaint);
canvas.drawBitmap(mBitmap, new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight()),
mRect, mPaint);
}
// 每 100 ms 更新一次
private Handler mHandler = new Handler();
private Runnable mRunnable = new Runnable() {
@Override
public void run() {
mStartX = mStartX + mSpeedX / 30;
mStartY = mStartY + mSpeedY / 30;
//mSpeedX = mSpeedX > 0 ? mSpeedX - 10 : mSpeedX + 10;
//mSpeedY = mSpeedY > 0 ? mSpeedY - 10 : mSpeedY + 10;
mSpeedX *= 0.97;
mSpeedY *= 0.97;
if (Math.abs(mSpeedX)
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?