欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

视图动画(补间动画+逐帧动画)

程序员文章站 2022-03-18 19:15:21
...

视图动画

✨执行XML中的动画

Animation animationScale = AnimationUtils.loadAnimation(this, R.anim.scale_one);
view.startAnimation(animationScale)

✨动画Animation属性

  • android:duration:一次动画持续时间(单位毫秒)
  • android:fillAfter:true:保持动画结束时的状态
  • android:fillBefore:true:动画结束时还原到初始化状态
  • android:fillEnabled:同fillBefore
  • android:repeatCount:指定动画重复次数,当取值为infinite时,表示无限循环。
  • android:repeatMode:用于设定重复的类型,有reverse和restart两个值。reverse表示倒序回放,restart表示重放,必须与repeatCount一起使用才能看到效果。
  • android:interpolator:插值器,其实就是指定的动画效果。

1、取消动画
void cancel()
2、将控件重置到动画开始前状态
void reset()
3、设置动画监听
setAnimationListener(Animation.AnimationListener listener);
回调函数如下:

  • onAnimationEnd():当动画结束时调用;
  • onAnimationRepeat():当动画重复时调用;
  • onAnimationStart():当动画开始时调用;

一、scale(渐变尺寸伸缩动画效果)

  • android:fromXScale:动画起始时,控件在X轴方向上相对自身的缩放比例,浮点值。(1.0表示自身无变化,0.5代表缩小1倍,2.0代表放大1倍)
  • android:toXScale:动画结束时,控件在X轴方向上相对自身的缩放比例,浮点值。
  • android:fromYScale:动画起始时,控件在Y轴方向上相对自身的缩放比例,浮点值。
  • android:toYScale:动画结束时,控件在Y轴方向上相对自身的缩放比例,浮点值。
  • android:pivotX:缩放起始点X轴坐标,可以是数值、百分数、百分数p三种方式,如50、50%、50%p。如果是数值,则表示在当前视图的左上角,即原点处加上50px,作为缩放起始点X轴坐标;如果是50%,则表示在当前控件的左上角加上自己宽度的50%作为缩放起始点X轴坐标;如果是50%p,则表示在当前控件的左上角加上父控件宽度的50%作为缩放起点X轴坐标。
  • android:pivotY:缩放起始点Y轴坐标,取值及含义与android:pivotX相同。

示例代码:

<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:fromXScale="0.1"
    android:fromYScale="0.1"
    android:toXScale="1.5"
    android:toYScale="1.5"
    android:pivotX="50"
    android:pivotY="50">
</scale>

代码的方式:
只要是第三个构造函数:其中pivotXType和pivotYType有以下三个取值:①、Animation.ABSOLUTE(对应的是数值),②、Animation.RELATIVE_TO_SELF(对应的是百分数),③、Animation.RELATIVE_TO_PARENT(对应的是百分数p)。

ScaleAnimation(float fromX,float toX,float fromY,float toY);
ScaleAnimation(float fromX,float toX,float fromY,float toY,float pivoteX,float pivoteY);
ScaleAnimation(float fromX,float toX,float fromY,float toY,int pivotXType,float pivotXValue,int pivotYType,float pivotYValue);

代码示例

ScaleAnimation scaleAnim = new ScaleAnimation(0.0f,1.4f,0.0f,1.4f,Animation.RELATION_TO_SELF,0.5f,Animation.RELATION_TO_SELF,0.5f);
scaleAnim.setDuration(1000);
view.startAnimation(scaleAnim);

当pivotX和pivotY的数值(不是百分值)较大时,动画效果是边平移边缩放的效果。当fromXScale和fromYScale的值不是从零开始的话,pivotX和pivotY的作用就被遮盖了,可能是起始点变化比起始缩放的效果早一些执行导致的(我也很奇怪)。还有当pivotX和pivotY有值且为正值时,view会从右王左开始缩放(至于为什么我想和Matrix的具体计算有关吧,待详细了解)。

二、alpha(实现渐变透明度动画效果)

  • android:fromAlpha:开始时的透明度,取值范围0.0~1.0,0.0表示全透明,1.0表示完全不透明。
  • android:toAlpha:动画结束时的透明度,取值范围0.0~1.0,0.0表示全透明,1.0表示完全不透明。

示例代码:

<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:fromAlpha="0"
    android:toAlpha="1">
</alpha>
AlphaAnimation(float fromAlpha,float toAlpha);
AlphaAnimation alphaAnim = new AlphaAnimation(1.0f,0.1f);

三、rotate(实现画面转移旋转动画效果)

  • android:fromDegrees:动画开始旋转时的角度位置,正值代表顺时针方向的度数,负值代表逆时针方向的度数。
  • android:toDegrees:动画结束时旋转到的角度位置,正值代表顺时针方向的度数,负值代表逆时针方向的度数。
    -android:pivotX:旋转中心点X轴坐标,默认旋转中心点是控件坐标原点。可以是数值、百分数、百分数p三种样式,比如50、50%、50%p,具体含义同之前所讲。
  • android:pivotY:旋转中心点Y轴坐标,具体同上。

示例代码:

<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:fillAfter="true"
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="360"></rotate>

构造函数

RotateAnimation(float fromDegree,float toDegree);
RotateAnimation(float fromDegree,float toDegree,float pivotX,float
pivoY);
RotateAnimation(float fromDegree,float toDegree,int pivotXType,float pivotXValue,int pivotYType,float
pivoYValue);

代码示例:

RotateAnimation rotateAnim=new RotateAnimation(0,-650,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);

四、translate(实现画面变化位置移动动画效果)

  • android:fromXDelta:起始点X轴坐标,可以是数值、百分数、百分数p三种样式,作用同之前所讲。
  • android:fromYDelta:起始点Y轴坐标,可以是数值、百分数、百分数p三种样式,作用同之前所讲。
  • android:toXDelta:终点X轴坐标。
  • android:toYDelta:终点Y轴坐标。

示例代码:

<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:fillAfter="false"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:toXDelta="80"
    android:toYDelta="80"></translate>

构造函数

TranslateAnimation(float fromXDelta,float toXDelta,float fromYDelta,float toYDelta);
TranslateAnimation(int fromXType,float fromXValue,int toXType,float toXValue,int fromYType,float fromYValue,int toYType,float toYValue);

代码示例

TranslateAnimation translateAnim = new TranslateAnimation(Animation.ABSOLUTE,0,Animation.ABSOLUTE,-80,Animation.ABSOLUTE,0,Animation.ABSOLUTE,-80);

五、set标签(定义动画集)

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:fillAfter="true">
    <alpha
        android:fromAlpha="0.0"
        android:toAlpha="1.0" />

    <scale
        android:fromXScale="0.0"
        android:fromYScale="0.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="1"
        android:toYScale="1" />

    <rotate
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="720" />
</set>

构造函数:其中shareInterpolator 参数的取值有true和false。当为true时,用于在AnimationSet类中定义一个插值器(Interpolator),其下面的所有动画共用该插值器;当为false时,则其下的动画定义各自的插值器。

AnimationSet(Context context , AttributeSet attrs);
AnimationSet(boolean shareInterpolator);

示例代码:

Animation alphaAnim = new AlphaAnimation(1.0f,1.0f);
Animation scalAnim=new ScaleAnimation(0.0f,1.4f,0.0f,1.4f,Animation.RELATION_TO_SELF,0.5f,Animation.RELATION_TO_SELF,0.5f);
Animation rotateAnim=new RotateAnimation(0,720,Animation.RELATION_TO_SELF,0.5f,Animation.RELATION_TO_SELF,0.5f);
AnimationSet setAnim = new AnimationSet(true);
setAnim.addAnimation(alphaAnim);
setAnim.addAnimation(scalAnim);
setAnim.addAnimation(rotateAnim);
setAnim.setDuration(3000);
setAnim.setFillAfter(true);
view.startAnimation(setAnim);

注意:在set标签中设置repeateCount属性是无效的,必须对每个动画单独设置才有作用。

逐帧动画

逐帧动画就是一帧挨着一帧的播放图片,就像放电影一样,既可以通过XML代码实现也可以通过Java代码实现。

一、XML实现

1、定义xml动画文件

将xml定义在/res下的anim或drawable目录中,代码如下:

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">

    <item
        android:drawable="@mipmap/spinner_0"
        android:duration="60" />
    <item
        android:drawable="@mipmap/spinner_1"
        android:duration="60" />
    <item
        android:drawable="@mipmap/spinner_2"
        android:duration="60" />
    <item
        android:drawable="@mipmap/spinner_3"
        android:duration="60" />
    <item
        android:drawable="@mipmap/spinner_4"
        android:duration="60" />
    <item
        android:drawable="@mipmap/spinner_5"
        android:duration="60" />
    <item
        android:drawable="@mipmap/spinner_6"
        android:duration="60" />
    <item
        android:drawable="@mipmap/spinner_7"
        android:duration="60" />
    <item
        android:drawable="@mipmap/spinner_8"
        android:duration="60" />
    <item
        android:drawable="@mipmap/spinner_9"
        android:duration="60" />
    <item
        android:drawable="@mipmap/spinner_10"
        android:duration="60" />
    <item
        android:drawable="@mipmap/spinner_11"
        android:duration="60" />
</animation-list>
  • 元素是必须的,并且必须作为根元素,可以包含一个或多个元素;
  • android:oneshot如果为true,那么动画只执行一次;如果定义为false,则一直循环。
  • android:drawable:指定此帧动画对应的图片资源。
  • android:duration:代表此帧动画持续的时间,是一个整数,单位毫秒。

2、设置ImageView

给ImageView设置动画资源,可以通过android:src 实现,也可以通过android:background实现。

3、AnimationDrawable开始动画

最后在代码中开始动画。代码展示:

//通过android:src方式设置后的获取方式
AnimationDrawable anim =(AnimationDrawable) image.getDrawable();
//通过android:background方式设置后的获取方式
AnimationDrawable anim =(AnimationDrawable) image.getBackground();
anim.start();

3、AnimationDrawable类

  • void start():开始播放逐帧动画。
  • void stop():停止播放逐帧动画。
  • int getDuration(int index):得到指定index的帧的持续时间。
  • Drawable getFrame(int index):得到指定index的帧所对应的Drawable对象。
  • int getNumberOfFrames():得到当前所有帧数量。
  • boolean isRunning():判断当前AnimationDrawable是否正在播放。
  • void setOneShot(boolean oneShot):设置AnimationDrawable是否执行一次,true代表执行一次,false代表循环执行。
  • boolean isOneShot():判断当前AnimationDrawable是否执行一次。
  • void addFrame(Drawable frame,int duration):为AnimationDrawable添加1帧,并设置持续时间。

二、代码实现

代码实现:

final AnimationDrawable anim = new AnimationDrawable();
for(int i=1;i<14;i++){
  int id=getResources().getIdentifier("spinner_"+i,"mipmap",getPackageName());
  Drawable drawable = getResources().getDrawable(id);
  anim.addFrame(drawable,60);
}
anim.setOneShot(false);
image.setBackgroundDrawable(anim);
anim.start();

这段代码的难点是通过文件名拿到文件:

int getIdentifier(String name , String defType , String defPackage);
  • String name: 所要查找资源ID的资源名称。
  • String defType:资源所在的文件类型。
  • String defPackage: 应用包名。