-
一、view动画(视图动画)
主要方法介绍:
//设置插值器:(后面会有插值器的介绍)
setInterpolator(Context context, int resID)
setInterpolator(Interpolator i)
//设置动画执行的时间:
setDuration(long durationMillis)
//设置动画重复次数
//注意:这里设置的是重复次数,即动画总的执行次数是1+repeatCount
setRepeatCount(int repeatCount)
//设置动画重复方式(参数有两个值:Animation.RESTART:重新开始 Animation.REVERSE:第二遍动画倒序执行),这个只有在动画执行次数大于1次是生效
setRepeatMode(int repeatMode)
//设置动画延迟时间
setStartTime(long startTimeMillis)
//设置动画停止时是否还显示控件 默认是false
setFillEnabled(boolean fillEnabled)
//设置动画停止时是否显示第一帧动画(即停止时是否在原始位置显示) 默认是true
setFillBefore(boolean fillBefore)
//设置动画停止时是否显示最后一帧动画(即停止时是否在终点位置显示) 默认是false
setFillAfter(boolean fillAfter)
//fillEnabled、fillBefore、fillAfter理解:
// - 1.fillEnabled=false时,fillBefore、fillAfter的设置无效
// 当三者都设置true时,等价于fillEnalbed=false
// - 2.fillEnabled=true&&fillBefore=true&&fillAfter=false 是系统默认的设置,即动画停止时会在原始位置显示控件
// - 3.fillEndabled=true&&fillBefore=false&&fillAfter=true 动画停止时会在终点显示控件
//设置动画的监听事件
setAnimationListener(Animation.AnimationListener listener)
public interface AnimationListener {
//动画开始
void onAnimationStart(Animation var1);
//动画结束
void onAnimationEnd(Animation var1);
//动画重复
void onAnimationRepeat(Animation var1);
}
上述方法都有对应的get方法
-
1.平移
将控件从指定的坐标(x1,y1)平滑的移动目的坐标处(x2,y2),使用方式有两种,一种是通过代码设置(推荐的方式),一种是通过xml文件设置(下文会有介绍)。
构造函数:
//参数:上下文对象,资源文件配置
public TranslateAnimation(Context context, AttributeSet attrs) {
}
//参数:起始点x坐标,起始点y坐标,终点x坐标,终点y坐标
public TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta) {
}
//参数:参数很多,但是很好理解,总体来说就两种类型type和value,
//type是后面value的类型,有两个值:Animation.RELATIVE_TO_SELF:value的值是相对于控件自身来测量的值,Animation.RELATIVE_TO_PARENT:value的值是相对于父布局来测量的。
//value是定义的具体的数值,fromXValue/fromYValue 是起始点坐标的x和y值,toXType/toYValue 是终点坐标的x和y值
public TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue, int fromYType, float fromYValue, int toYType, float toYValue) {
}
使用:
//使用的是4个参数的构造函数,指定了起点和终点的坐标
//获取屏幕的宽和高
WindowManager windowManager = getWindowManager();
Display display = windowManager.getDefaultDisplay();
Point point = new Point();
display.getSize(point);
int screenWidth = point.x;//屏幕宽
int screenHeight = point.y;//屏幕高
TranslateAnimation translateAnimation = new TranslateAnimation(0,
screenWidth - imageView.getWidth(),
0,
screenHeight - imageView.getHeight());
//动画停止时在终点显示控件
translateAnimation.setFillEnabled(true);
translateAnimation.setFillBefore(false);
translateAnimation.setFillAfter(true);
//重复次数,此时动画一共会执行3次
translateAnimation.setRepeatCount(2);
//重复的模式
// Animation.RESTART:重新开始 Animation.REVERSE:第二遍动画倒序执行
translateAnimation.setRepeatMode(Animation.REVERSE);
translateAnimation.setDuration(2000);
imageView.startAnimation(translateAnimation);
-
2.旋转
将控件绕某一点进行旋转
构造函数:
//参数:上下文对象,资源文件配置
public RotateAnimation(Context context, AttributeSet attrs) {
}
//参数:开始的角度,最终的角度(即:从fromDegrees旋转到toDegrees,比如从45度旋转到90度),没有指定轴点坐标,默认会以控件的左上角的点为轴点旋转
public RotateAnimation(float fromDegrees, float toDegrees) {
}
//参数:开始的角度,最终的角度,旋转轴点x坐标和y坐标
public RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY) {
}
//参数:开始的角度,最终的角度,后面四个参数定义的是旋转轴点坐标,type和value参考上面平移的解释
public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) {
}
使用:
//这里使用的是按照控件的中心点旋转,如果使用两个参数的构造器,则按照控件的左上角的点旋转
RotateAnimation rotateAnimation = new RotateAnimation(0, 90,
imageView.getWidth() / 2, imageView.getHeight() / 2);
rotateAnimation.setDuration(2000);
rotateAnimation.setFillEnable(true);
rotateAnimation.setFillBefore(false);
rotateAnimation.setFillAfter(true);
//可以设置其他属性
imageView.startAnimation(rotateAnimation);
-
3.缩放
将控件按照一定的比例进行放大或缩小。
构造函数:
//参数:上下文对象,资源配置
public ScaleAnimation(Context context, AttributeSet attrs) {
}
//参数:将x轴从fromX缩放到toX,将y轴从fromY缩放到toY,默认是以控件的左上角的角点作为缩放的基点
//理解:将x的宽度从(fromX*控件的宽度)缩放到(toX*控件的宽度),将控件的高度从(fromY*控件的高度)缩放到(toY*控件的高度),缩放是以控件的宽高为基数进行操作的,比如(1f,0.5f,1f,0.5f)是将控件的宽高缩小一倍
public ScaleAnimation(float fromX, float toX, float fromY, float toY) {
}
//参数:将x轴从fromX缩放到toX,将y轴从fromY缩放到toY,pivotX和pivotY是放大缩小的轴点坐标
public ScaleAnimation(float fromX, float toX, float fromY, float toY, float pivotX, float pivotY) {
}
//参数比上面的构造器多了type值,type和value的含义同上面动画的一样
public ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) {
}
使用:
//将控件整体缩放一倍,以左上角的点
ScaleAnimation scaleAnimation = new ScaleAnimation(1f, 0.5f,
1f, 0.5f);
scaleAnimation.setDuration(2000);
scaleAnimation.setFillEnabled(true);
scaleAnimation.setFillBefore(false);
scaleAnimation.setFillAfter(true);
imageView.startAnimation(scaleAnimation);
-
4.渐变(改变透明度)
构造器:
//参数:上下文对象,配置的参数
public AlphaAnimation(Context context, AttributeSet attrs) {
super(context, attrs);
}
//参数:起始透明度,最终透明度
public AlphaAnimation(float fromAlpha, float toAlpha) {
}
使用:
AlphaAnimation alphaAnimation = new AlphaAnimation(1f, 0.2f);
alphaAnimation.setDuration(2000);
alphaAnimation.setFillAfter(true);
imageView.startAnimation(alphaAnimation);
上面写的都是基本的用法,一般来说动画都没有单一的,都是组合动画,组合动画的使用主要用到一个类:AnimationSet,通过它将单一的动画组合起来。
AnimationSet的构造器:
//参数:上下文对象,配置的参数
public AnimationSet(Context context, AttributeSet attrs) {
super(context, attrs);
}
// 参数:是否使用用一个插值器,如果复杂动画的每一种动画都有自己的插值器则设置为false,true表示多种动画使用同一个插值器
public AnimationSet(boolean shareInterpolator) {
}
使用:
ScaleAnimation scaleAnimation = new ScaleAnimation(1f, 0.5f, 1f, 0.5f);
RotateAnimation rotateAnimation = new RotateAnimation(0, 180, imageView.getWidth() / 2, imageView.getHeight() / 2);
AlphaAnimation alphaAnimation = new AlphaAnimation(1f, 0.5f);
AnimationSet animationSet = new AnimationSet(false);
animationSet.addAnimation(scaleAnimation);
animationSet.addAnimation(rotateAnimation);
animationSet.addAnimation(alphaAnimation);
animationSet.setFillAfter(true);
animationSet.setDuration(2000);
imageView.startAnimation(animationSet);
使用AnimationSet创建的组合动画是同时执行的,即多个子动画同步运行,如果想子动画依次执行,就不能使用animationSet,需要给每个子动画增加事件监听器,在上一个动画执行完毕的时候执行下一个动画,如:
scaleAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
imageView.startAnimation(rotateAnimation);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
view动画还可以通过xml进行设置,这种方式需要提前设置好,但是在实际项目中有很多动画需要的参数是无法提前知道的,因此通过java代码设置动画是最好的方式。但是不妨碍我们进行学习。xml文件都放在项目的res/anim文件夹中。
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fillAfter="true">
<translate
android:fromXDelta=""
android:fromYDelta=""
android:toXDelta=""
android:toYDelta="" />
<scale
android:fromXScale=""
android:fromYScale=""
android:pivotX=""
android:pivotY=""
android:toXScale=""
android:toYScale="" />
<rotate
android:fromDegrees=""
android:pivotX=""
android:pivotY=""
android:toDegrees="" />
<alpha
android:fromAlpha=""
android:toAlpha="" />
</set>
在项目中调用该动画(R.anim.myanimation是上面创建的动画的xml文件):
Animation animation = AnimationUtils.loadAnimation(this, R.anim.myanimation);
imageView.startAnimation(animation);
view动画的对控件的改变只是视觉上的改变,并没有从根本上改变,比如平移动画,只是视觉上平移,实际上view还是在原来的位置,比如点击事件,只有点击原始的位置才能触发。
-
二、帧动画
帧动画就是将一系列图片在一定时间内一张一张的显示出来的过程。主要使用的是AnimationDrawable类。
构造器:
public AnimationDrawable() {
}
主要方法:
//visible设置动画是否可见,
//restart用来设置动画重启时从第几帧开始显示,restart=true,动画重启时从第一帧开始显示,restart=false动画重启时从暂停时的那一帧开始显示
public boolean setVisible(boolean visible, boolean restart) {}
//开始动画
public void start() {}
//停止动画
public void stop() {}
//是否正在执行
public boolean isRunning(){}
//获取动画的帧数,也就是获取有多少张图
public int getNumberOfFrames(){}
//获取指定下标的帧的图
public Drawable getFrame(int index){}
//获取指定下标的帧的持续时间
public int getDuration(int i){}
//是否执行一次
public boolean isOneShot(){}
//设置动画只执行一次
public void setOneShot(boolean oneShot)
//增加子视图和对应的持续时间
public void addFrame(@NonNull Drawable frame, int duration) {}
使用:
animationDrawable = new AnimationDrawable();
Drawable drawable1 = getResources().getDrawable(R.drawable.image1);
Drawable drawable2 = getResources().getDrawable(R.drawable.image2);
Drawable drawable3 = getResources().getDrawable(R.drawable.image3);
Drawable drawable4 = getResources().getDrawable(R.drawable.image4);
Drawable drawable5 = getResources().getDrawable(R.drawable.image5);
animationDrawable.addFrame(drawable1, 200);
animationDrawable.addFrame(drawable2, 200);
animationDrawable.addFrame(drawable3, 200);
animationDrawable.addFrame(drawable4, 200);
animationDrawable.addFrame(drawable5, 200);
animationDrawable.setOneShot(true);
//开始动画
private void startFrameAnimation() {
imageView.setImageDrawable(animationDrawable);
animationDrawable.start();
}
//结束动画
private void stopFrameAnimation() {
animationDrawable.stop();
}
帧动画使用简单,但是容易引起OOM,必须要使用时尽量避免使用大尺寸的图片。
-
三、属性动画
属性动画是Android3.0提出的,主要通过数值的不断变化,来改变控件的属性,从而达到产生动画的效果。并且其可以使用于任何java对象上,不在局限于控件。 属性动画主要依赖两个类:ValueAnimator和ObjectAnimator。 ####1、ValueAnimator
构造器:
//无参构造器,一般不使用
public ValueAnimator() {
}
常用方法:
//参数:参数可为多个,数值从第一个参数以int的类型过渡到第2个参数,再从第2个参数过渡到第3个参数,以此类推
//注:如果参数为一个,查看源码,发现如果参数为一个,动画将不执行,因为系统不知道动画的开始值
public static ValueAnimator ofInt(int... values)
//设置过渡的值
public void setIntValues(int... values)
//参数:多个颜色值,颜色进行平滑过渡
public static ValueAnimator ofArgb(int... values)
//参数:以float的类型平滑过渡
public static ValueAnimator ofFloat(float... values)
public void setFloatValues(float... values)
//参数:evaluator是估值器(下面会有介绍) 多个对象进行过渡
public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values)
public void setObjectValues(Object... values)
//参数:设置动画持续时间
public ValueAnimator setDuration(long duration)
//设置动画到指定的时间点,playTime在0和动画持续时间之内,大于持续时间按照持续时间处理
public void setCurrentPlayTime(long playTime)
//延时播放动画
public void setStartDelay(long startDelay)
//设置重复次数
public void setRepeatCount(int value)
//设置重复模式
public void setRepeatMode(@RepeatMode int value)
//设置数值变化监听器
public void addUpdateListener(AnimatorUpdateListener listener)
//移除所有的监听器
public void removeAllUpdateListeners()
//移除指定的监听器
public void removeUpdateListener(AnimatorUpdateListener listener)
//设置插值器(下面会有解释)
public void setInterpolator(TimeInterpolator value)
//设置估值器
public void setEvaluator(TypeEvaluator value)
//启动动画
public void start()
//取消动画
public void cancel()
//动画结束
public void end()
//动画重新开始
public void resume()
//动画暂停
public void pause()
使用:
ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 10);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//从1过渡到10的时候中间值
Log.i("info", "" + (int)animation.getAnimatedValue());
}
});
valueAnimator.setDuration(10);
valueAnimator.start();
属性动画的本质就是利用数值的不断变化,改变对象的属性,从而达到动画的效果。如下,是将imageview的宽度从原始宽度过渡到屏幕宽度:
WindowManager windowManager = getWindowManager();
Point outPoint = new Point();
windowManager.getDefaultDisplay().getSize(outPoint);
int width = outPoint.x;//屏幕的宽度
int imageViewWidth = imageView.getLayoutParams().width;
ValueAnimator valueAnimator = ValueAnimator.ofInt(imageViewWidth, width);
valueAnimator.setDuration(5000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int currenWidth = (int) animation.getAnimatedValue();
//控件设置新的宽度
imageView.getLayoutParams().width = currenWidth;
//重新绘制
imageView.requestLayout();
}
});
valueAnimator.start();
从上面可以看出ValueAnimator是在值改变以后手动修改对象的属性,来实现动画的。
2、ObjectAnimator
构造器:
//无参构造器,一般不使用
public ObjectAnimator() {
}
常用方法:
//参数:动画执行的对象,执行动画的对象的属性名字,动画的起始值、过渡值、最终值
public static ObjectAnimator ofInt(Object target, String propertyName, int... values)
//参数:动画执行的对象,执行动画的属性名字x和y,执行动画的路径
//其实就是将path的x、y指定给object的(xPropertyName、yPropertyName)
public static ObjectAnimator ofInt(Object target, String xPropertyName, String yPropertyName, Path path)
//颜色值过渡动画
public static ObjectAnimator ofArgb(Object target, String propertyName, int... values)
//参数:动画执行的对象,属性的名称,估值器,过渡的对象或最终的对象
public static ObjectAnimator ofObject(Object target, String propertyName,
TypeEvaluator evaluator, Object... values)
其他方法和ValueAnimator的差不多,从上面的方法名以及源码知道ObjectAnimator是自动将数值的变化指定给target对象的属性,其中propertyName就是target对象的某个属性的名字。而自动赋值的前提是target对象的propertyName属性有get和set方法,否则该动画是无法执行的。
ObjectAnimator其实底层也是使用deValueAnimator来进行播放动画的,先解释一个插值器和估值器,以及他们的使用。
-
估值器(Evaluator)
估值器主要是用来决定数据是如何过渡的,定义过渡的规则。系统有已经写好的估值器,比如:IntEvaluator、IntEvaluator等,当我们需要动画按照自定义的规则执行时,就需要自定义的估值器。
使用:
public class MyCustomEvaluator implements TypeEvaluator<Integer> {
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
//写入自定义的规则
return null;
}
}
主要就是实现TypeEvaluator的evaluate这个方法,参数:fraction是动画进行的百分比值,startValue和endValue是动画的起始值和最终值。
例子(均匀的改变imageview的透明度)
上代码:
public class MyCustomEvaluator implements TypeEvaluator<Float> {
@Override
public Float evaluate(float fraction, Float startValue, Float endValue) {
//匀速改变数值
return (Float) (startValue + (endValue - startValue) * fraction);
}
}
在Activity中:
private void startAnimator() {
ObjectAnimator objectAnimator = ObjectAnimator.ofObject(imageView, "alpha", new MyCustomEvaluator(), 1f, 0.3f);
objectAnimator.setDuration(2000);
objectAnimator.start();
}
-
插值器(Interpolator)
插值器主要是决定动画过渡的速度,设置是匀速、加速、还是减速或者其他。系统提供了9种插值器供选择。
- AccelerateInterpolator(@android:anim/accelerate_interpolator) 加速
- OvershootInterpolator (@android:anim/overshoot_interpolator)快速完成,超出结束值在返回到结束值
- AccelerateDecelerateInterpolator(@android:anim/accelerate_decelerate_interpolator) 先加速,在减速
- AnticipateInterpolator(@android:anim/anticipate_interpolator)先退后,再加速执行
- AnticipateOvershootInterpolator(@android:anim/anticipate_overshoot_interpolator )先退后,再加速,然后再超出结束值时返回结束值
- BounceInterpolator(@android:anim/bounce_interpolator) 最后阶段弹球的效果
- CycleInterpolator(@android:anim/cycle_interpolator) 周期性执行动画
- DecelerateInterpolator(@android:anim/decelerate_interpolator)减速执行动画
- LinearInterpolator(@android:anim/linear_interpolator)匀速执行动画
当上述插值器无法满足要求时就需要自定义的插值器。
使用:
public class MyCustomInterpolator implements TimeInterpolator {
@Override
public float getInterpolation(float input) {
//此处写入逻辑规则
return 0;
}
}
文中有写的不对的欢迎大家指出,一起学习,一起进步。
送上demo,内有购物车增加商品的动画