前面给我们分析了 原因1: 原因2: 补间动画只是改变了 1、属性动画都是通过 我们了解了下面6个类的基本用法,就基本彻底掌握了属性动画 首先我们先来看一下 方法中第一个参数 方法中第三个参数 添加一些代码来看一下效果 该动画效果表示控件 运行效果: 用 Java代码中通过加载该xml启动动画 值动画通过控制值的变化,之后 手动赋值给对象的属性,从而实现动画。 下面我们来添加值动画,在值动画的监听函数里 来获取值得变化,根据值的变化对控件设置相应的属性。这里的属性可以是控件的任意属性。 效果如下 前面的 效果如下: 前面的动画属性的变换都是均匀变换,可以通过 从下面的运行的效果可以看出,用了加速差值器以后,该图片alpha动画前期变化很慢,都后面变化越来越快。 我们还可以通过自定义类实现 在前面的 这些方法动都需要传一个TypeEvaluator,我们先来看下这个类的源码 从 从 我们也可以以该方法为例 实现一个自定义的估值器实现一个背景颜色值的变化 我们先定义一个默认估值器类 再自定义一个View,在该类中画一个矩形框 自顶一个View在布局文件中添加如下 将在估值器加到动画中,该动画作用在我们自定义的View上 效果如下:本文目录

属性动画概述
Android中的帧动画和补间动画的特点和用法
Android动画之补间动画用法最全详解
Android 动画之帧动画用法详解Android官方在Anrdoid 3.0以后又推出了一种新的动画即属性动画,既然前面的帧动画和补间动画能帮助我们实现大部分的Android动画效果,那么官方为什么还要推出这种新的属性动画呢?补间动画作用的对象是View,也就是作用的对象是Android中的控件,如ImageView、Button、TextView等,也可以作用在布局上如LinearLayout、ConstraintLayout、RelativeLayout等,但是对于一些不是View的对象,无法对这些对象进行动画操作。比如我们要对某个控件的某个属性做进行动画操作,如其颜色,这个颜色也可以看成一个对象,但其并不是View对象,补间动画就无法实现,属性动画可以对这个颜色值做动画, 能实现一些更加复杂的动画效果。View的视觉效果,而不会真正去改变View的属性

比如我们对一个图片进行AlphaAnimation,并在动画前后打印其值Log.i("MainActivity","动画开始前mImageView alpha="+mImageView.getAlpha()); animation = new AlphaAnimation(0, 1); animation.setDuration(2000); mImageView.startAnimation(animation); Log.i("MainActivity","动画结束后mImageView alpha="+mImageView.getAlpha()); 
从打印的结果可以看出,补间动画并没有改变View的属性值,而属性动画不但会帮助我们实现View动画的一些视觉效果,而且还能改变View的属性值。属性动画用法
ValueAnimator 类和ObjectAnimator 类来完成,其中ObjectAnimator类是对对象做动画,ValueAnimator 类是对值做动画。
2、PropertyValueHolder类可以同时执行多个动画,AnimatorSetl类可以将多个动画按一定的秩序先后执行。
3、TypeEvaluator估值器和Interpolator 差值器
对象动画(ObjectAnimator)
ObjectAnimator类是属性动画中非常重要的一个类,可以通过该类对View不仅可以实现一些基本的移、旋转、缩放和透明度四种基本变换动画,还能实现一些其他属性值的变换动画。
实现方式既可以通过Java代码,也可以通过XML方式来实现,下面我们来分别介绍下两种方式基本用法。方法1:Java代码实现对象动画
ObjectAnimator类最基本的方法 public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) { ObjectAnimator anim = new ObjectAnimator(target, propertyName); anim.setFloatValues(values); return anim; } Object target 的作用对象通常是View,也就是Android中的控件或布局。
方法中第二个参数String propertyName 通常是需要执行动画的属性,具体值如下表所示
属性
值的用法
rotation
以屏幕方向为轴的旋转度数
alpha
透明度
translationX / translationY
X/Y方向的位移
scaleX /scaleY
X/Y方向的缩放倍数
rotationX / rotationY
以X/Y轴为轴的旋转度数
float... values 表示属性的变换范围,该参数可以传多个值。ImageView imageView = findViewById(R.id.imageView); ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "alpha", 1f, 0f, 1f); animator.setDuration(5000); animator.start(); ImageView的透明度在5s内由1变换到0,再由0变回 1。效果如下:

ObjectAnimator的其他方法使用如下: ImageView imageView = findViewById(R.id.imageView); ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "alpha", 1f, 0f, 1f); animator.setDuration(2000); //动画延迟500ms执行 animator.setStartDelay(500); //执行重复次数 +1 animator.setRepeatCount(3); // 设置动画重复播放模式 RESTART -执行完一遍后重新执行 // REVERSE -执行完一遍后 从末位置往前执行 animator.setRepeatMode(ValueAnimator.RESTART); //监听值变换 animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Log.i("MainActivity","value:" +animation.getAnimatedValue()); } }); animator.start();

onAnimationUpdate回调方法的部分值打印如下

方法2:XML实现对象动画

XML实现对象动画
1、在res目录下新建animator文件夹
2、animator文件夹下创建动画XML文件,如animator_alpha.xml
往该xml文件中输入如下代码<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="https://schemas.android.com/apk/res/android" android:propertyName="alpha" android:valueFrom="1" android:valueTo="0" android:valueType="floatType" /> ImageView imageView = findViewById(R.id.imageView); Animator animator = AnimatorInflater.loadAnimator(Main2Activity.this, R.animator.animator_alpha); animator.setTarget(imageView); animator.start(); 值动画(ValueAnimator)
ValueAnimator的核心方法如下ValueAnimator ofFloat(float... values) -- 浮点型数值 ValueAnimator ofInt(int... values) -- 整型数值 ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) -- 自定义对象类型 final ImageView imageView = findViewById(R.id.imageView); ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f); anim.setDuration(5000); anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float currentValue = (float) animation.getAnimatedValue(); Log.d("MainActivity", "cuurent value is " + currentValue); imageView.setAlpha(currentValue); } }); anim.start();

从下面的打印结果中也可以看出,值动画返回了一系列值。

PropertyValueHolder
PropertyValueHolder可以让前面的一些动画同时执行。 ImageView imageView = findViewById(R.id.imageView); PropertyValuesHolder alphaProper = PropertyValuesHolder.ofFloat("alpha", 0.5f, 1f); PropertyValuesHolder scaleXProper = PropertyValuesHolder.ofFloat("scaleX", 0f, 1f); PropertyValuesHolder scaleYProper = PropertyValuesHolder.ofFloat("scaleY", 0f, 1f); PropertyValuesHolder translationXProper = PropertyValuesHolder.ofFloat("translationX", -100, 100); PropertyValuesHolder translationYProper = PropertyValuesHolder.ofFloat("translationY", -100, 100); PropertyValuesHolder rotationProper = PropertyValuesHolder.ofFloat("rotation", 0, 360); ValueAnimator animator = ObjectAnimator.ofPropertyValuesHolder(imageView, alphaProper, scaleXProper, scaleYProper,translationXProper,translationYProper,rotationProper); animator.setDuration(5000); animator.start(); 
动画组合(AnimatorSet)
PropertyValueHolder类能实现将多个动画同时执行,AnimatorSet类不仅能让多个动画同时执行,还能让多个动画按一定的顺序执行,同时也能穿插多个动画同时执行。
主要的方法如下:after(Animator anim)将现有动画插入到传入的动画之后执行
after(long delay) 将现有动画延迟指定毫秒后执行
before(Animator anim) 将现有动画插入到传入的动画之前执行
with(Animator anim) 将现有动画和传入的动画同时执行 ImageView imageView = findViewById(R.id.imageView); ObjectAnimator rotate = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 360f); ObjectAnimator translationX = ObjectAnimator.ofFloat(imageView, "translationX", -100, 100f); ObjectAnimator translationY = ObjectAnimator.ofFloat(imageView, "translationY", -100, 100f); ObjectAnimator scaleX = ObjectAnimator.ofFloat(imageView, "scaleX", 0, 1f); ObjectAnimator scaleY = ObjectAnimator.ofFloat(imageView, "scaleY", 0, 1f); ObjectAnimator alpha = ObjectAnimator.ofFloat(imageView, "alpha", 1f, 0f, 1f); AnimatorSet animSet = new AnimatorSet(); animSet.play(rotate) .with(alpha) .after(scaleX) .before(translationX) .after(1000) .before(translationY) .with(scaleY); animSet.setDuration(5000); animSet.start();

差值器(Interpolator)
差值器(Interpolator)来控制值变化的速率ImageView imageView = findViewById(R.id.imageView); ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1f); animator.setDuration(5000); //加速查值器,参数越大,速度越来越快 animator.setInterpolator(new AccelerateInterpolator(5)); animator.start(); 
系统我们提供了九种默认的差值器分别如下:
动画名称
效果
AccelerateInterpolator
加速查值器,参数越大,速度越来越快
DecelerateInterpolator
减速差值起,和加速查值器相反
AccelerateDecelerateInterpolator
先加速后减速
AnticipateInterpolator
先后退在加速前进
AnticipateOvershootInterpolator
以X/Y轴为轴的旋转度数
BounceInterpolator
弹球效果插值
CycleInterpolator
周期运动插值
LinearInterpolator
匀速插值
OvershootInterpolator
先快速完成动画,再回到结束样式
Interpolator接口来实现一些自定义的差值器效果。估值器(TypeEvaluator)
值动画(ValueAnimator)中和对象动画(ObjectAnimator)有一个传对象的方法:ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) ObjectAnimator ofObject(Object target, String propertyName, TypeEvaluator evaluator, Object... values) public interface TypeEvaluator<T> { public T evaluate(float fraction, T startValue, T endValue); } TypeEvaluator估值器的源码可以看出该类的作用就是告诉动画,如何从起始值过度到结束值。
Android源码中有好几个类实现来该接口,也就是系统提供的一些默认估值器, 我们以FloatEvaluator为例看下其实现代码。public class FloatEvaluator implements TypeEvaluator<Number> { public Float evaluate(float fraction, Number startValue, Number endValue) { float startFloat = startValue.floatValue(); return startFloat + fraction * (endValue.floatValue() - startFloat); } } FloatEvaluator的实现可以看出在evaluate方法中用结束值减去初始值,算出它们之间的差值,然后乘以fraction这个系数,再加上初始值,那么就得到当前动画的值了MyTypeEvaluator,该类自定义了颜色过渡的方式package com.lucashu.animation; import android.animation.TypeEvaluator; public class MyTypeEvaluator implements TypeEvaluator<String> { private int mCurrentRed = -1; private int mCurrentGreen = -1; private int mCurrentBlue = -1; @Override public String evaluate(float fraction, String startValue, String endValue) { int startRed = Integer.parseInt(startValue.substring(1, 3), 16); int startGreen = Integer.parseInt(startValue.substring(3, 5), 16); int startBlue = Integer.parseInt(startValue.substring(5, 7), 16); int endRed = Integer.parseInt(endValue.substring(1, 3), 16); int endGreen = Integer.parseInt(endValue.substring(3, 5), 16); int endBlue = Integer.parseInt(endValue.substring(5, 7), 16); // 初始化颜色的值 if (mCurrentRed == -1) { mCurrentRed = startRed; } if (mCurrentGreen == -1) { mCurrentGreen = startGreen; } if (mCurrentBlue == -1) { mCurrentBlue = startBlue; } // 计算初始颜色和结束颜色之间的差值 int redDiff = Math.abs(startRed - endRed); int greenDiff = Math.abs(startGreen - endGreen); int blueDiff = Math.abs(startBlue - endBlue); int colorDiff = redDiff + greenDiff + blueDiff; if (mCurrentRed != endRed) { mCurrentRed = getCurrentColor(startRed, endRed, colorDiff, 0, fraction); } else if (mCurrentGreen != endGreen) { mCurrentGreen = getCurrentColor(startGreen, endGreen, colorDiff, redDiff, fraction); } else if (mCurrentBlue != endBlue) { mCurrentBlue = getCurrentColor(startBlue, endBlue, colorDiff, redDiff + greenDiff, fraction); } // 将计算出的当前颜色的值组装返回 String currentColor = "#" + getHexString(mCurrentRed) + getHexString(mCurrentGreen) + getHexString(mCurrentBlue); return currentColor; } /** * 根据fraction值来计算当前的颜色。 */ private int getCurrentColor(int startColor, int endColor, int colorDiff, int offset, float fraction) { int currentColor; if (startColor > endColor) { currentColor = (int) (startColor - (fraction * colorDiff - offset)); if (currentColor < endColor) { currentColor = endColor; } } else { currentColor = (int) (startColor + (fraction * colorDiff - offset)); if (currentColor > endColor) { currentColor = endColor; } } return currentColor; } /** * 将10进制颜色值转换成16进制。 */ private String getHexString(int value) { String hexString = Integer.toHexString(value); if (hexString.length() == 1) { hexString = "0" + hexString; } return hexString; } } public class MyView extends View { private String color; private Paint mPaint; public MyView(Context context, AttributeSet attrs) { super(context, attrs); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(Color.WHITE); } public String getColor() { return color; } public void setColor(String color) { this.color = color; mPaint.setColor(Color.parseColor(color)); invalidate(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawRect(0, 0, 500,500, mPaint); } } <com.lucashu.animation.MyView android:id="@+id/myview" android:layout_width="200dp" android:layout_height="200dp" android:layout_marginBottom="100dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> MyView imageView = findViewById(R.id.myview); ObjectAnimator anim = ObjectAnimator.ofObject( imageView,"color", new MyTypeEvaluator(), "#0000FF","#FF0000"); anim.setDuration(5000); anim.start();

本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算
官方软件产品操作指南 (170)