二、Android动画学习---属性动画
目录
八、Property Animation(属性动画)ValueAnimator基本使用
(一) 概述
1、为什么引入Property Animator(属性动画)
(二) ValueAnimator简单使用
1、初步使用ValueAnimator
2、实例使用ValueAnimator
(三) 常用方法
1、ofInt与ofFloat
(四) 常用函数
1.添加监听器
2.取消监听器
(六) Evaluator:
本文章作为学习总结
尊重原创老师自定义控件三部曲之动画篇(四)——ValueAnimator基本使用_启舰的博客-CSDN博客
八、Property Animation(属性动画)ValueAnimator基本使用
(一) 概述
Property Animation(属性动画)包括ValueAnimator和ObjectAnimator
1、为什么引入Property Animator(属性动画)
我提出一个假设:请问大家,如何利用补间动画来将一个控件的背景色在一分钟内从绿色变为红色?这个效果想必没办法仅仅通过改变控件的渐入渐出、移动、旋转和缩放来实现吧,而这个效果是可以通过Property Animator完美实现的
这就是第一个原因:Property Animator能实现补间动画无法实现的功能
大家都知道,补间动画和逐帧动画统称为View Animation,也就是说这两个动画只能对派生自View的控件实例起作用;而Property Animator则不同,从名字中可以看出属性动画,应该是作用于控件属性的!正因为属性动画能够只针对控件的某一个属性来做动画,所以也就造就了他能单独改变控件的某一个属性的值!比如颜色!这就是Property Animator能实现补间动画无法实现的功能的最重要原因。
我们得到了第二点不同:View Animation仅能对指定的控件做动画,而Property Animator是通过改变控件某一属性值来做动画的。
假设我们将一个按钮从左上角利用补间动画将其移动到右下角,在移动过程中和移动后,这个按钮都是不会响应点击事件的。这是为什么呢?因为补间动画仅仅转变的是控件的显示位置而已,并没有改变控件本身的值。View Animation的动画实现是通过其Parent View实现的,在View被drawn时Parents View改变它的绘制参数,这样虽然View的大小或旋转角度等改变了,但View的实际属性没变,所以有效区域还是应用动画之前的区域;我们看到的效果仅仅是系统作用在按钮上的显示效果,利用动画把按钮从原来的位置移到了右下角,但按钮内部的任何值是没有变化的,所以按钮所捕捉的点击区域仍是原来的点击区域。(下面会举例来说明这个问题)
这就得到了第三点不同:补间动画虽能对控件做动画,但并没有改变控件内部的属性值。而Property Animator则是恰恰相反,Property Animator是通过改变控件内部的属性值来达到动画效果的
(二) ValueAnimator简单使用
1、初步使用ValueAnimator
要使用ValueAnimaiton,总共有两步:
第一步:创建ValueAnimator实例
ValueAnimator animator = ValueAnimator.ofInt(0,400);
animator.setDuration(1000);
animator.start();
在这里我们利用ValueAnimator.ofInt创建了一个值从0到400的动画,动画时长是1s,然后让动画开始。从这段代码中可以看出,ValueAnimator没有跟任何的控件相关联,那也正好说明ValueAnimator只是对值做动画运算,而不是针对控件的,我们需要监听ValueAnimator的动画过程来自己对控件做操作。
第二步:添加监听
上面的三行代码,我们已经实现了动画,下面我们就添加监听:
ValueAnimator animator = ValueAnimator.ofInt(0,400);
animator.setDuration(1000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (int)animation.getAnimatedValue();
Log.d("qijian","curValue:"+curValue);
}
});
animator.start();
在上面的代码中,我们通过addUpdateListener添加了一个监听,在监听传回的结果中,是表示当前状态的ValueAnimator实例,我们通过animation.getAnimatedValue()得到当前值。然后通过Log打印出来,
- 总而言之就是两点:
- ValueAnimator只负责对指定的数字区间进行动画运算
- 我们需要对运算过程进行监听,然后自己对控件做动画操作
2、实例使用ValueAnimator
public class MainActivity extends AppCompatActivity {//private Button btn;private TextView tv;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tv = (TextView)findViewById(R.id.tv);//也可以写成//btn = (Button)findViewById(R.id.btn);//btn.setOnClickListener(new View.OnClickListener(){});findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {public void onClick(View v) {
// TextView tv = (TextView) findViewById(R.id.tv);
// //加载动画
// Animation animation = AnimationUtils.loadAnimation(MainActivity.this,R.anim.scaleanim);
// tv.startAnimation(animation);doAnimation();}});tv.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(MainActivity.this, "clicked me", Toast.LENGTH_SHORT).show();}});}private void doAnimation() {//构造一个ValueAnimator实例,让其计算的值是从0到800ValueAnimator animator = ValueAnimator.ofInt(0, 800);//动画持续时间,单位毫秒animator.setDuration(1000);//对计算过程进行监听animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {int curValue = (int) animation.getAnimatedValue();//在监听过程中,通过layout函数来改变textview的位置。// 这里注意了,我们是通过layout函数来改变位置的,我们知道layout函数在改变控件位置时是永久性的,// 即通过更改控件left,top,right,bottom这四个点的坐标来改更改坐标位置的,而不仅仅是从视觉上画在哪个位置,// 所以通过layout函数更改位置后,控件在新位置是可以响应点击事件的。tv.layout(curValue, curValue, curValue + tv.getWidth(), curValue + tv.getHeight());//layout()函数中上下左右点的坐标是以屏幕坐标来标准的。所以在效果图中可以看到,textview的运动轨迹是从屏幕的左上角(0,0)点运行到(400,400)点。}});animator.start();}
}
(三) 常用方法
1、ofInt与ofFloat
在上面的例子中,我们使用了ofInt函数,与它同样功能的还有一个函数叫ofFloat,下面我们先看看他们的具体声明:
public static ValueAnimator ofInt(int... values)
public static ValueAnimator ofFloat(float... values)
示例:
ValueAnimator animator = ValueAnimator.ofFloat(0f,400f,50f,300f);
animator.setDuration(3000);
Float curValueFloat = (Float)animation.getAnimatedValue();
通过getAnimatedValue()来获取当前运动点的值,大家可能会疑问为什么要转成Float类型,我们先来看看getAnimatedValue()的声明:
Object getAnimatedValue();
(四) 常用函数
先做个汇总,这部分将讲述的方法有:
ValueAnimator setDuration(long duration) 设置动画时长,单位是毫秒
Object getAnimatedValue(); 获取ValueAnimator在运动时,当前运动点的值
void start() 开始动画
void cancel() 取消动画
void setRepeatCount(int value) 设置循环次数,设置为INFINITE表示无限循环
void setRepeatMode(int value) 设置循环模式,value取值有RESTART,REVERSE,
取值为ValueAnimation.RESTART时,表示正序重新开始,
当取值为ValueAnimation.REVERSE表示倒序重新开始。
- 两个监听器
1.添加监听器
前面,我们讲过一个添加监听器animator.addUpdateListener,以监听动画过程中值的实时变化,其实在ValueAnimator中共有两个监听器:
3、两个监听器
(1)、添加监听器
前面,我们讲过一个添加监听器animator.addUpdateListener,以监听动画过程中值的实时变化,其实在ValueAnimator中共有两个监听器:
/**
* 监听器一:监听动画变化时的实时值
*/
public static interface AnimatorUpdateListener {
void onAnimationUpdate(ValueAnimator animation);
}
//添加方法为:public void addUpdateListener(AnimatorUpdateListener listener)
/**
* 监听器二:监听动画变化时四个状态
*/
public static interface AnimatorListener {
void onAnimationStart(Animator animation);
void onAnimationEnd(Animator animation);
void onAnimationCancel(Animator animation);
void onAnimationRepeat(Animator animation);
}
//添加方法为:public void addListener(AnimatorListener listener)
关于监听器一:AnimatorUpdateListener就是监听动画的实时变化状态,在onAnimationUpdate(ValueAnimator animation)中的animation表示当前状态动画的实例。这里就不再细讲这个监听器了,这里我们主要讲讲监听器AnimatorListener;
在AnimatorListener中,主要是监听Animation的四个状态,start、end、cancel、repeat;当动画开始时,会调用onAnimationStart(Animator animation)方法,当动画结束时调用onAnimationEnd(Animator animation),当动画取消时,调用onAnimationCancel(Animator animation)函数,当动画重复时,会调用onAnimationRepeat(Animator animation)函数。
添加AnimatorListener的方法是addListener(AnimatorListener listener) ;
下面我们就举个例子来看一下AnimatorListener的使用方法。
我们在上面doRepeatAnim()函数的基础上,添加上AnimatorListener,代码如下:
代码如下:
private ValueAnimator doAnimatorListener(){
ValueAnimator animator = ValueAnimator.ofInt(0,400);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (int)animation.getAnimatedValue();
tv.layout(tv.getLeft(),curValue,tv.getRight(),curValue+tv.getHeight());
}
});
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
Log.d("qijian","animation start");
}
@Override
public void onAnimationEnd(Animator animation) {
Log.d("qijian","animation end");
}
@Override
public void onAnimationCancel(Animator animation) {
Log.d("qijian","animation cancel");
}
@Override
public void onAnimationRepeat(Animator animation) {
Log.d("qijian","animation repeat");
}
});
animator.setRepeatMode(ValueAnimator.REVERSE);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setDuration(1000);
animator.start();
return animator;
}
在上面的代码中,我们是在doRepeatAnim()函数的基础上,又添加了AnimatorListener()以监听它的状态,并把这些状态打印出来。
2.取消监听器
上面我们讲了如何添加监听函数,下面我们来看看如何移除监听器:
/**
* 移除AnimatorUpdateListener
*/
void removeUpdateListener(AnimatorUpdateListener listener);
void removeAllUpdateListeners();
/**
* 移除AnimatorListener
*/
void removeListener(AnimatorListener listener);
void removeAllListeners();
针对AnimatorUpdateListener和AnimatorListener,每个监听器都有两个方法来移除;我们就以移除AnimatorListener来简单讲一下,removeListener(AnimatorListener listener)用于在animator中移除指定的监听器,而removeAllListeners()用于移除animator中所有的AnimatorListener监听器;
下面上在添加监听器的例子基础上,不改变doAnimatorListener()的代码,仍然是textview做动画时添加AnimatorListener的状态监听。然后点击cancelAnim时,移除AnimatorListener,代码如下:
AnimatorListener的代码:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
…………
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
repeatAnimator = doAnimatorListener();
}
});
btnCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
repeatAnimator.removeAllListeners();
}
});
}
doAnimatorListener的代码与上面的一样,就不再重复贴了,当点击btnCancel时移除animator中所有的AnimatorListener,但注意的是,我们在移除AnimatorListener后,并没有cancel动画效果,所以动画会一直不停的运动下去。但移除AnimatorListener之后,Log应该就不会再打印了。
在效果图中,在动画循环了三次之后,我们点击btnCancel移除所有的AnimatorListener;打印tag如下:
可见只打印了循环三次以前的log,在移除我们添加的AnimatorListener之后,我们打印log的代码就不会再执行了,所以也就不会再有log了。
好了,有关监听器的部分,我们就到这里了
(六) Evaluator:
插值器数值转换器,数值进度转换为对应的数值
ofInt()对应的Evaluator类名为IntEvaluator
ofFaloat()对应的Evaluator类名为FloatEvaluator
在设置Evaluator时,是通过animator.setEvaluator()函数来实现的
二、Android动画学习---属性动画相关推荐
- Android进阶学习-属性动画(使用Animator封装特效工具类1)
其实关于Animation动画还是有点不足的,动画过后容易造成事件丢失,测试下面的例子 TranslateAnimation =new TranslateAnimation(0, 0, 100, 10 ...
- android 从底部网上的平移动画_Android属性动画,看完这篇够用了吧
转载自作者新小梦 随着APP的开发周期演进,APP不再满足基础的功能保障,需要有较好视觉体验和交互操作.那么动画效果是必不可少的,动画有帧动画,补间动画,属性动画等等. 本文通过一些简单常见的动画效果 ...
- android 属性动画还原,属性动画和补间动画
动画的分类 今天我们将会探讨动画的学习,Android的动画分成三类 1. Tween Animation(补间动画.视图动画):通过对场景里的对象不断做图像变换(平移.缩放.旋转)产生的动画效果,即 ...
- Android -- 三种动画(帧动画、View动画、属性动画)
Android的动画分为了三种, 分别是 帧动画.View动画.属性动画 一:帧动画 帧动画就是顺序播放一组预先定义好的图片,就类似于我们观看视频,就是一张一张的图片连续播放. 帧动画的使用很简单,总 ...
- Android动画攻略—帧动画、补间动画、属性动画
前言 动画时Android开发中使用频率比较高的功能. 对Android提供的补间动画,帧动画以及属性动画做出归纳总结. 目录 1. 帧动画 帧动画总体实现比较简单,其实现本身是实现一个图片集的连续播 ...
- Android的三种动画详解(帧动画、View动画、属性动画)
Android的动画分为了三种, 分别是 帧动画.View动画.属性动画. 1.帧动画 帧动画就是顺序播放一组预先定义好的图片,就类似于我们观看视频,就是一张一张的图片连续播放. 帧动画的使用很简单, ...
- Android Property Animation属性动画:scale缩放动画(4)
Android Property Animation属性动画:scale缩放动画(4) 和之前我写的附录文章1,2,3相似,本文将接着使用Android Property Animation属性 ...
- 【Android 属性动画】属性动画 Property Animation 与 视图动画 View Animation 区别
文章目录 一.动画效果添加对象 二.动画效果类型 三.动画效果与实际属性 四.开发复杂程度 属性动画 Property Animation 可以为 任何对象 ( View 对象 / 非 View 对象 ...
- 【Android 属性动画】属性动画 Property Animation 简介 ( 属性动画简介 | 属性动画特性 )
文章目录 一.属性动画简介 二.属性动画特性 一.属性动画简介 属性动画简介 : 1.动画制作框架 : 属性动画系统 , 允许你 将任何可变的操作制作成动画 , 其功能很强大 ; 2.基本功能 : 使 ...
最新文章
- 三菱触摸屏usb驱动安装_2020年三菱EXPRESS SWB和LWB:竟然是日系中唯一没有屏幕的面包车...
- BZOJ 2111 [ZJOI2010]Perm 排列计数:Tree dp + Lucas定理
- 解题报告——例题 5-6团体队列(Team Queue UVa 540)——31行代码解决
- 聚合复合_聚合复合微生物菌剂的功能
- Codeforces Round #712 (Div. 2)
- EasyUI(前端框架)
- 超9000万LoRa节点,全球物联网的事实标准已形成?
- Atitit.web三大编程模型 Web Page Web Forms 和 MVC
- 视频教程-第03章-二进制、八进制、十进制、十六进制之间的转换-网络技术
- ThinkPHP框架短信接口
- 创业过程中技术真的那么重要吗
- Mapping Spiking Neural Networks的论文汇总以及思考
- @RequestBody、 @RequestParam 、 @PathVariable 和 @Vaild 注解
- 火爆的AI绘画+红包封面+春联+节日头像+创作者入驻小程序源码
- PCL:demeanPointCloud ❤️ 去点云质心
- debian 6.0.5下RT5370无线网卡驱动安装
- 西铁城CL-S631无法打印,打印测试空白
- 微信小程序关注公众号模板显示隐藏问题
- keepalived(haproxy高可用、haproxy高可用双主、lvs+keepalived)
- ELL解决:libstdc++.so.6: version `CXXABI_1.3.9' not found (required by bin/opencv_test_core)?
热门文章
- mysql期中考试题及答案_MySQL数据库考试题与答案
- 嵌入式系统 - 任务
- 无“网络中立”的时代,我们该如何保证网络安全
- pop3协议的几种状态
- 问“新没电恐惧症“的因,修续航赛道的果
- softmax函数的正推原理——softmax前世今生系列(1)
- (五)field ii:彩色血流成像
- The GridView 'gv ' fired event RowEditing which wasn 't handled.
- Hadoop搭建、环境配置
- BZOJ 4666 小z的胡话