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两种动画: 逐帧动画的原理很简单,就是将一个完整的动画拆分成一张张单 ...
随机推荐
- 26个精选的JavaScript面试问题
译者按: 从各个平台精选整理出26道由浅入深的题目助你面试 原文: Top 26 JavaScript Interview Questions I Wish I Knew 译者: Fundebug 为 ...
- css实现照片上传的加号框
css实现照片上传的加号框
- jQuery js 中return false,e.preventDefault(),e.stopPropagation()的区别(事件冒泡)
有时候遇到冒泡事件很烦人,真的..... 1.e.stopPropagation()阻止事件冒泡 <head> <title></title> <script ...
- CDQ分治小结
CDQ分治小结 warning:此文仅用博主复习使用,初学者看的话后果自负.. 复习的时候才发现以前根本就没写过这种东西的总结,简单的扯一扯 cdq分治的经典应用就是解决偏序问题 比如最经典的三维偏序 ...
- 【20181031】arcgis10.6破解不成功的问题
首先需要下好正确版本的crack文件,license10.6文件夹里应该有ARCGIS.exe和service.txt两个文件,我的问题就是因为crack文件不完整,没有ARCGIS.exe文件,所以 ...
- React报错:Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix,
今天在开发时报了以下错误,记录一下 我们不能在组件销毁后设置state,防止出现内存泄漏的情况 出现原因直接告诉你了,组件都被销毁了,还设置个锤子的state啊 解决方案: 利用生命周期钩子函数:co ...
- VUE基于ElementUI搭建的简易单页后台
一.项目链接 GitHub 地址: https://github.com/imxiaoer/ElementUIAdmin 项目演示地址:https://imxiaoer.github.io/Eleme ...
- maven(三):maven项目结构及其运行机制
在上一篇中讲了如何创建maven项目,现在回到那个项目 项目结构 src/main/java:java代码目录 src/main/resources:资源目录,比如spring.xml文件,prope ...
- linux设置自动更换壁纸
#!/bin/bash let n=0 files=($HOME/wallpapers/*.jpg) count=${#files[@]} while [ 1 ] do let "n=n%$ ...
- lua保留n位小数方法
time:2015/04/21 1. string.format() function GetPreciseDecimal(nNum, n) if type(nNum) ~= "number ...