美文网首页技术笔记
动画其实很简单——视图动画使用

动画其实很简单——视图动画使用

作者: Gzw丶南山 | 来源:发表于2017-02-09 14:44 被阅读41次

    视图动画介绍

    视图动画(Animation)是Android提供给我们的一个动画工具,API Level 1的就已经存在,使用起来其实都是按照同样的套路就可以了,而API Level 11(Android 3.0.x)后推出的属性动画也是为了想要替代它,毕竟视图动画视图动画,顾名思义就知道它是对视图进行操作,也就是View,但也就只能对View进行操作,两者的区别下次等我介绍完属性动画再讲。不过如果你已经使用了视图动画也不用着急全部都换成属性动画。

    官方在介绍视图动画的时候把它分为了两类,一个是补间动画,一个逐帧动画,补间动画里面就是我们经常会用到平移、旋转、缩放、渐变,逐帧动画就是我们平常所说的帧动画,你需要有很多张图片从而组成一组图片集。

    动画使用套路

    在正式介绍视图动画使用之前我们先介绍一下动画本身套路,我们使用动画的时候都需要考虑什么不论是在哪里使用都可怎么考虑,如下图:

    如何正确考虑动画分为哪些.png

    我们分析了动画本身实现时应该考虑哪些,也分析了对应写动画时和代码实现中应该去做哪些,那么下面我们开始介绍视图动画的使用吧。

    视图动画使用

    既然我们已经总结了动画使用完整套路,那么我们就可以直接开始去写代码了,当然使用的过程中我会分为xml形式和code形式分开写同样效果的代码。

    补间动画

    效果(sorry占的地方太大了):


    效果图.gif

    1.渐变
    其实说来渐变算是最简单的动画,因为只要考虑初始状态和结束状态和持续时间就可以了,包括了xml实现和代码实现

    xml的标签表示意义可以查看 https://developer.android.com/guide/topics/resources/animation-resource.html#View

    //  如果使用xml来实现动画则需要在res包下创建anim包,然后再创建xxx动画的xml 例:anim_alpha.xml
    <alpha xmlns:android="http://schemas.android.com/apk/res/android"
            android:duration="1800"          //  动画持续时间
            android:fromAlpha="0"            //  一开始是透明的
            android:toAlpha="1.0"/>          //  最后变成完全显示
    //  使用AnimationUtils加载资源文件夹下的动画
    Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_alpha);
    //  mAnimTarget是一个我已经写好的ImageView,通过调用View的startAnimation()来执行动画
    mAnimTarget.startAnimation(animation);
    
    
    //  代码实现
    //  从1到0表示了目标View从可见到不可见
    Animation animation = new AlphaAnimation(1, 0);
    //  动画持续2s
    animation.setDuration(2000);
    mAnimTarget.startAnimation(animation);
    

    2.平移
    其实这个名称有点不太准确,并不是说平移只是平着移动,而是从一个点到另一个点,比如我让我的View只是往下移动,根据Android的坐标系,x往右为正,y往下为正,那么从自身(0,0)出发到(0,200)就是往下移动了一段距离,代码如下:

    //  xml实现
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:duration="1800"
               android:fromXDelta="0"          //  x起始点
               android:fromYDelta="0"          //  y起始点
               android:toXDelta="150"          //  x终点
               android:toYDelta="150"/>        //  y终点
    Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_translate);
    //  mAnimTarget是一个我已经写好的ImageView,通过调用View的startAnimation()来执行动画
    mAnimTarget.startAnimation(animation);
    
    //  代码实现
    //  构造TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)
    Animation animation = new TranslateAnimation(0, 0, 0, 200);
    //  动画持续2s
    animation.setDuration(2000);
    mAnimTarget.startAnimation(animation);
    

    3.旋转
    无论是旋转还是缩放默认都是从左上角开始的,而gif中是以中心点开始旋转或者缩放的,实现如下:

    //  xml实现 持续1.8s 以中心点开始放大一倍
    <scale xmlns:android="http://schemas.android.com/apk/res/android"
           android:duration="1800"
           android:fromXScale="1"
           android:fromYScale="1"
           android:pivotX="50%"              //  50%表示自身中心
           android:pivotY="50%"              //  50%表示自身中心         
           android:toXScale="2"
           android:toYScale="2"/>
    
    //  pivotX和pivotY的值可以为浮点数或百分比
    //  表示为:相对于对象左边缘的像素(例如“5”),
    //  相对于对象左边缘的百分比(例如“5%”)
    //  或相对于父容器的左边缘的百分比(例如“ 5%p“)。
    
    //  代码实现
    //  ScaleAnimation(float fromX, float toX, float fromY, float toY,
                int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
    //  RELATIVE_TO_SELF 0.5 以自己为中心点开始缩放
    Animation animation = new ScaleAnimation(1, 2, 1, 2, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
    //  动画持续2s
    animation.setDuration(2000);
    mAnimTarget.startAnimation(animation)
    

    4.缩放
    代码如下:

    //  xml 使用同其他
    <rotate xmlns:android="http://schemas.android.com/apk/res/android"
            android:duration="1800"
            android:fromDegrees="0"
            android:pivotX="50%"
            android:pivotY="50%"
            android:toDegrees="360"/>
    
    //  代码实现
    //  RELATIVE_TO_SELF 0.5 以自己为中心点开始旋转
    Animation animation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
    //  动画持续2s
    animation.setDuration(2000);
    mAnimTarget.startAnimation(animation)
    

    <br />
    看完上面四个单个的动画你可能会察觉到这些动画效果最后并没有被保留,而是又恢复了动画开始前的样子,所以如果你想要保留执行动画后的效果,只需要通过Animation调用一个方法就可以了,调用这个方法后执行效果就会被保留了,但是这里我们需要注意,View的真实位置并没有被改变,而是还是动画开始前的那个位置,你可以通过对View设置侦听就可以发现了。

    //  动画结束就停在那个位置 但实际的控件位置没变
    animation.setFillAfter(true);
    

    5.组合动画
    我们先来看一下效果图,这里有用到了平移,旋转,缩放,渐变,先向上平移然后另外三个同时运行,startOffset是延迟时间,xml如下:

    RecScreen170209155615.gif
    <set xmlns:android="http://schemas.android.com/apk/res/android">
    
        <!-- 实现一个图片从底部先升起然后通过斜着飞出手机的效果,所分解为以下若干动画 -->
    
        <!-- 先实现平移动画向上x轴不变, y为负 -->
        <translate
            android:duration="2000"
            android:fromXDelta="0"
            android:fromYDelta="0"
            android:toXDelta="0"
            android:toYDelta="-500"/>
    
        <!-- 完成向上的的动作接下里要做同时做三件事, 往屏幕外面飞, 涉及到平移、缩放和渐变 -->
    
        <!-- startOffset是延迟时间 -->
        <rotate
            android:duration="2000"
            android:fromDegrees="0"
            android:pivotX="50%"
            android:pivotY="50%"
            android:startOffset="2000"
            android:toDegrees="-45"/>
    
        <scale
            android:duration="2000"
            android:fromXScale="1"
            android:fromYScale="1"
            android:pivotX="50%"
            android:pivotY="50%"
            android:startOffset="2000"
            android:toXScale="2"
            android:toYScale="2"/>
    
        <alpha
            android:duration="2000"
            android:fromAlpha="1"
            android:startOffset="2000"
            android:toAlpha="0"/>
    
    </set>
    

    6.插值器
    插值器就是我们所说的时间轴,它可以让我们设置动画的变化率,通过调用Animation.setInterpolator()就可以了,然而Interpolator下面有很多之类,我们这次就不上效果图了(为啥那么大)...我们来介绍一下它的子类。

    Interpolator.png
    //  AccelerateDecelerateInterpolator变化率开始和结束缓慢,但加速通过中间
    //  AccelerateInterpolator变化率开始缓慢,然后加速
    //  AnticipateInterpolator变化开始向后然后向前
    //  AnticipateOvershootInterpolator变化开始向后,然后向前和超过目标值,最后回到最终值
    //  BounceInterpolator有边界的插值器
    //  CycleInterpolator为了其手动设置周期
    //  DecelerateInterpolator变化率快速开始然后减速, 可手动设置Factor
    //  贝塞尔相关FastOutLinearInInterpolator,FastOutSlowInInterpolator,LinearOutSlowInInterpolator
    //  LinearInterpolator变化率是恒定的
    //  可手动设置OvershootInterpolator张力值
    

    <br />

    逐帧动画

    帧动画的话,你需要很多张可以连起来的图片从而组成一个动画去展示给用户,使用如下:

    //  在drawable包下创建一个xml文件并以animation-list为根目录,
    //  然后每一帧都是一个Item,指明Item的资源和持续时间
     <!-- Animation frames are wheel0.png through wheel5.png
         files inside the res/drawable/ folder -->
     <animation-list android:id="@+id/selected" android:oneshot="false">
        <item android:drawable="@drawable/wheel0" android:duration="50" />
        <item android:drawable="@drawable/wheel1" android:duration="50" />
        <item android:drawable="@drawable/wheel2" android:duration="50" />
        <item android:drawable="@drawable/wheel3" android:duration="50" />
        <item android:drawable="@drawable/wheel4" android:duration="50" />
        <item android:drawable="@drawable/wheel5" android:duration="50" />
     </animation-list>
    
    // 把写好的资源帧动画xml设置被对应的控件的背景
    // Load the ImageView that will host the animation and
    // set its background to our AnimationDrawable XML resource.
    ImageView img = (ImageView)findViewById(R.id.spinning_wheel_image);
    img.setBackgroundResource(R.drawable.spin_animation);
    
    // 通过VIew的getBackground()获取AnimationDrawable,
    // 然后调用start()就好了,当然也可以调用stop()停止它
    // Get the background, which has been compiled to an
    AnimationDrawable object.
    AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();
    
    // Start the animation (looped playback by default).
    frameAnimation.start();
    

    <br />
    以上代码均已放到我的Github中

    地址 https://github.com/GzwJaaaelu/AnimApp

    我希望可以站在初学者&自学者的角度把Android中的知识点很清楚的介绍给大家,希望大家喜欢。 如果有错误希望指出来,有问题或者没看懂,都可以来问我的

    相关文章

      网友评论

        本文标题:动画其实很简单——视图动画使用

        本文链接:https://www.haomeiwen.com/subject/ldtybttx.html