Android 利用属ObjectAnimator,AnimatorSet性动画绘制一个弹球,加速下落,到底部时挤压,然后减速上弹
属性动画主要的几个类介绍:
1.ValueAnimator:这个类提供了一个简单的计时引擎运行动画动画计算值和设置目标对象。注意:使用该类时一般都是用:ObjectAnimator,而基于ObjectAnimator执行的属性动画,都是根据java的反射机制来设置的,因此设置动画的目标对象的属性必须有getter 和setter方法。
setDuration:设置动画的时间
setInterpolator:设置一个插入器,例如:减速器(DecelerateInterpolator),加速器(AccelerateInterpolator),当然也可以自定义,自定义时只需要继承这两个类就行了,这里就不做讨论了。
setEvaluator:设置评估者
1.ArgbEvaluator:这种评估者可以用来执行类型之间的插值整数值代表ARGB颜色。
2.FloatEvaluator:这种评估者可以用来执行浮点值之间的插值。
3.IntEvaluator:这种评估者可以用来执行类型int值之间的插值。
4.RectEvaluator:这种评估者可以用来执行类型之间的插值矩形值。
setRepeatCount:设置动画的重复次数(是一个int类型的值)
setRepeatMode:设置动画模式
start:启动动画
2.AnimatorSet:这个类为一组特定的动画指定顺序。
总要方法如下:
play:该方法创建一个构造器对象用于创建约束。
playTogether:设置同时运行一组动画
pase:暂停一个正在运行的动画
resume:重新运行暂停后的动画
isRunning:判断动画是否正在运行
isStarted:判断动画是否已经运行了
start:开始动画
3.AnimatorSet.Builder创建一个用于约束动画的建造器
after(Animator):执行前面的动画后执行该动画
after(long delay):延迟n毫秒之后执行动画
before(Animator):执行前面动画前执行动画
with(Animator):和前面动画一块执行
4.ShapeDrawable:模型drawable,创建时需要传入一个图形模型
以下是一个简单的Demo例子用于测试以上情况(小球加速下落挤压后减速上弹)
一、BackgroundView.java
package cn.yw.lib.animation; import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator; /**
* 属性动画,背景轮询切换
* 为什么要使用SurfaceView而不是用View:
* 1.这里稍作解释,由于SurfaceView继承了View,绘制起来和SurfaceView没有太大的区别,
* 2.SurfaceView本身自带双缓冲技术,能够更好的支持动画操作
*
*
* @author yw-tony
*
*/
@SuppressLint("NewApi")
public class BackgroundView extends SurfaceView implements
SurfaceHolder.Callback, Runnable { private SurfaceHolder holder;
private ShapeHolder shapHolder; public BackgroundView(Context context) {
super(context);
this.holder = this.getHolder();
this.holder.addCallback(this);
} /**
* 创建一个小球
*/
private void createABall(float x, float y) {
OvalShape oval = new OvalShape();
//设置拓原模型的宽高都为50f,即模型为原型
oval.resize(50f, 50f);
//创建一个模型drawable
ShapeDrawable drawable = new ShapeDrawable(oval);
shapHolder = new ShapeHolder(drawable);
int red = (int) (Math.random() * 255);
int green = (int) (Math.random() * 255);
int blue = (int) (Math.random() * 255);
int color = 0xff000000 | red << 16 | green << 8 | blue;
Paint paint = drawable.getPaint(); // new Paint(Paint.ANTI_ALIAS_FLAG);
int darkColor = 0xff000000 | red / 4 << 16 | green / 4 << 8 | blue / 4;
RadialGradient gradient = new RadialGradient(37.5f, 12.5f, 50f, color,
darkColor, Shader.TileMode.CLAMP);
//设置画笔颜色
paint.setShader(gradient);
shapHolder.setPaint(paint);
//设置小球的初始位置
shapHolder.setX(x);
shapHolder.setY(y);
} @Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() != MotionEvent.ACTION_DOWN
&& event.getAction() != MotionEvent.ACTION_MOVE) {
return false;
}
//创建一个小球
createABall(event.getX(), event.getY());
//设置动画的Y轴活动范围
float startY = shapHolder.getY();
float endY = getHeight() - 50f;
// int duration = (int)(500 * ((h - eventY)/h));
// 小球弹跳动画的时间为500毫秒
int duration = 500;
ValueAnimator bounceAnim = ObjectAnimator.ofFloat(shapHolder, "y",
startY, endY);
bounceAnim.setDuration(duration);
// 加速器,小球会加速下落
bounceAnim.setInterpolator(new AccelerateInterpolator());
// 以下几个是挤压动画 ValueAnimator squashAnim1 = ObjectAnimator.ofFloat(shapHolder, "x",
////设置x周的动画范围
shapHolder.getX(), shapHolder.getX() - 25f);
//设置压缩动画时间为下落动画时间的四分之一
squashAnim1.setDuration(duration / 4);
squashAnim1.setRepeatCount(1);
squashAnim1.setRepeatMode(ValueAnimator.REVERSE);
//挤压是做减速运动
squashAnim1.setInterpolator(new DecelerateInterpolator());
ValueAnimator squashAnim2 = ObjectAnimator.ofFloat(shapHolder, "width",
//设置小球宽度动画
shapHolder.getWidth(), shapHolder.getWidth() + 50);
squashAnim2.setDuration(duration / 4);
squashAnim2.setRepeatCount(1);
squashAnim2.setRepeatMode(ValueAnimator.REVERSE);
//小球做减速运动
squashAnim2.setInterpolator(new DecelerateInterpolator());
//设置伸展动画
ValueAnimator stretchAnim1 = ObjectAnimator.ofFloat(shapHolder, "y",
endY, endY + 25f);
stretchAnim1.setDuration(duration / 4);
stretchAnim1.setRepeatCount(1); stretchAnim1.setInterpolator(new DecelerateInterpolator());
stretchAnim1.setRepeatMode(ValueAnimator.REVERSE);
ValueAnimator stretchAnim2 = ObjectAnimator.ofFloat(shapHolder,
"height", shapHolder.getHeight(), shapHolder.getHeight() - 25);
stretchAnim2.setDuration(duration / 4);
stretchAnim2.setRepeatCount(1);
stretchAnim2.setInterpolator(new DecelerateInterpolator());
stretchAnim2.setRepeatMode(ValueAnimator.REVERSE); ValueAnimator bounceBackAnim = ObjectAnimator.ofFloat(shapHolder, "y",
endY, startY);
bounceBackAnim.setDuration(duration);
// 减速器
bounceBackAnim.setInterpolator(new DecelerateInterpolator()); //设置动画对象的顺序
AnimatorSet bouncer = new AnimatorSet();
//先加速下落然后再执行挤压动画1
bouncer.play(bounceAnim).before(squashAnim1);
//播放挤压动画1的同事播放挤压动画2
bouncer.play(squashAnim1).with(squashAnim2);
bouncer.play(squashAnim1).with(stretchAnim1);
bouncer.play(squashAnim1).with(stretchAnim2);
//执行完挤压动画后执行小球弹起动画
bouncer.play(bounceBackAnim).after(stretchAnim2);
//开始执行动画
bouncer.start();
return true;
} private void drawBall() {
Canvas canvas = null;
try {
canvas = holder.lockCanvas();
if (canvas != null) {
canvas.drawColor(Color.GRAY);
canvas.save();
//如果小球为空则不执行绘制动作
if (shapHolder != null) {
canvas.translate(shapHolder.getX(), shapHolder.getY());
shapHolder.getShape().draw(canvas);
}
canvas.restore();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
//解锁画布
if (holder != null) {
holder.unlockCanvasAndPost(canvas);
}
} catch (Exception e) {
e.printStackTrace();
}
}
} @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) { } @Override
public void surfaceCreated(SurfaceHolder holder) {
//开启绘制线程
new Thread(this).start();
} @Override
public void surfaceDestroyed(SurfaceHolder holder) { } @Override
public void run() {
try {
//此处为死循环,大家在写的时候可以加上一个boolean变量值,当用户点击回退键(back)时,结束线程
while (true) {
drawBall();
Thread.sleep(200);
}
} catch (Exception e) {
e.printStackTrace();
}
} }
二、BackgroundViewActivity.java
package cn.yw.lib.animation; import android.app.Activity;
import android.os.Bundle; public class BackgroundViewActivity extends Activity{
private BackgroundView view;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
view = new BackgroundView(this);
setContentView(view);
} }
Android 利用属ObjectAnimator,AnimatorSet性动画绘制一个弹球,加速下落,到底部时挤压,然后减速上弹的更多相关文章
- UI特效--Android利用ViewFlipper实现屏幕切换动画效果
.屏幕切换指的是在同一个Activity内屏幕见的切换,最长见的情况就是在一个FrameLayout内有多个页面,比如一个系统设置页面:一个个性化设置页面.2.介绍ViewFilpper类ViewFl ...
- Android利用ViewFlipper实现屏幕切换动画效果
1.屏幕切换指的是在同一个Activity内屏幕见的切换,最长见的情况就是在一个FrameLayout内有多个页面,比如一个系统设置页面:一个个性化设置页面. 2.介绍ViewFilpper类 Vie ...
- Android 利用二次贝塞尔曲线模仿购物车加入物品抛物线动画
Android 利用二次贝塞尔曲线模仿购物车加入物品抛物线动画 0.首先.先给出一张效果gif图. 1.贝塞尔曲线原理及相关公式參考:http://www.jianshu.com/p/c0d7ad79 ...
- Android利用温度传感器实现带动画效果的电子温度计
概述 Android利用温度传感器实现带动画效果的电子温度计. 详细 代码下载:http://www.demodashi.com/demo/10631.html 一.准备工作 需要准备一部带有温度传感 ...
- 我的Android进阶之旅------>Android利用温度传感器实现带动画效果的电子温度计
要想实现带动画效果的电子温度计,需要以下几个知识点: 1.温度传感器相关知识. 2.ScaleAnimation动画相关知识,来进行水印刻度的缩放效果. 3.android:layout_weight ...
- [转]Android自定义控件三部曲系列完全解析(动画, 绘图, 自定义View)
来源:http://blog.csdn.net/harvic880925/article/details/50995268 一.自定义控件三部曲之动画篇 1.<自定义控件三部曲之动画篇(一)—— ...
- 【Android - 基础】之Animator属性动画
1 概述 在3.0系统之前,Android给我们提供了逐帧动画Frame Animation和补间动画Tween Animation两种动画: 1) 逐帧动画的原理很简单,就是 ...
- android.animation(4) - ObjectAnimator的ofInt(), ofFloat()(转)
一.概述 1.引入 上几篇给大家讲了ValueAnimator,但ValueAnimator有个缺点,就是只能对数值对动画计算.我们要想对哪个控件操作,需要监听动画过程,在监听中对控件操作.这样使用起 ...
- 【Android - 进阶】之Animator属性动画
1.概述 在3.0系统之前,Android给我们提供了逐帧动画Frame Animation和补间动画Tween Animation两种动画: 逐帧动画的原理很简单,就是将一个完整的动画拆分成一张张单 ...
随机推荐
- Spring - constructor-arg和property的使用示例
一.说明 constructor-arg:通过构造函数注入. property:通过setter对应的方法注入. 二.property使用实例 1.Model代码: public cla ...
- 【CSS学习】--- 文本样式
一.前言 CSS文本属性可以定义文本的外观.通过文本属性,可以定义文本的颜色.字符间距,对齐文本,装饰文本,对文本进行缩进,等等. CSS常用的文本属性目录: text-align 文本对齐属性 te ...
- jquery绑定点击事件的三种写法
一.用jquery动态绑定点击事件的写法 部分代码: <script type="text/javascript"> $(document).ready(functio ...
- python自动化开发-5b
python的常用模块(续) time和datetime模块 time模块和datetime模块举例 例子:获取当前时间 import datetime,time now = time.strftim ...
- Apex计划作业框架的实现
Apex计划作业框架的实现 在本文中,我们实现一个简单的"计划作业框架",用于实现数据的定时自动处理. Apex相关接口 Apex中提供了一组接口用来实现数据的处理.我们主要使用以 ...
- SoapUI 利用SoapUI进行简单的接口并发测试
利用SoapUI进行简单的接口并发测试 by:授客 QQ:1033553122 测试环境: SoapUI Pro 5.1.2 步骤如下 1. 把请求添加到测试套件 1.1. 途径1 1.新 ...
- Oracle 关闭数据库(未使用Oracle Restart)
Oracle关闭数据库(未使用Oracle Restart) by:授客 QQ:1033553122 SHUTDOWN [选项] 选项说明: NORMAL-语句执行后,不允许创建新的连接:等待所有当前 ...
- Git服务器配置及本地克隆提交、服务器获取
1.服务器Git安装配置 相关链接 相关链接 注意ssh-keygen .修改权限 权限: 相关链接 2.本地获取 git clone name@ip:服务器项目位置 相关链接 3.创建 ...
- 三步搞定Centos 7 上特定版本的 docker 安装
由于国内网络原因,使用centos的用户yum源常用国内的阿里云.现在把centos7上安装docker的详细过程记录如下: 一.配置centos7的yum源(阿里云) 1.cd /etc/yum. ...
- 【 PostgreSQL】查询某模式下所有表的分布键信息
想看下某模式下所有表创建的分布键是否合理,查找系统表文档拼出如下sql,亲们如果有更好的sql或者意见欢迎留言! SELECT aaa.nspname AS "模式名", ...