Android动画介绍

Android动画

ViewAnimation

  • 属性
    • 插值器
      Interpolator 是个接口,系统已经实现了几种插值器,在使用的时候,以LinearInterpolator为例

      在Xml中:

      android:interpolator="@android:anim/linear_interpolator"

      在代码中(Kotlin):

      interpolator = LinearInterpolator()
  • 部分属性中不同的值类型

    Java xml description
    Animation.ABSOLUTE 数值 10、50等数值,表示据坐标原点的距离
    Animation.RELATIVE_TO_SELF 数值% xml:50%, java:0.5, 再传入类型参数Animation.RELATIVE_TO_SELF,表示据坐标原点的距离为当前控件当前方向上50%的长度
    Animation.RELATIVE_TO_PARENT 数值%p xml:50%p, java:0.5, 再传入类型参数Animation.RELATIVE_TO_PARENT,表示据坐标原点的距离为父控件当前方向上50%的长度
  1. Common: 共有的属性

    name description
    duration 动画的执行时间 , ms
    fillAfter 保持动画执行结束后的状态 , boolean
    fillBefore 恢复到动画执行前的状态 , boolean
    interpolator 插值器,动画执行的过程中的速率变化, 比如先快后慢、匀速等
    repeatMode 动画再次执行的模式: reverse, 逆向执行;restart,从头开始
    repeatCount 动画执行的次数: infinite(-1)表示无限循环,要在具体的Animation中设置才有效
  2. Alpha

    name description
    toAlpha 动画结束时的透明度, 0.0~1.0
    fromAlpha 动画开始时的透明度, 0.0~1.0
  1. Rotate

    name description
    pivotX 作为旋转中心的X的值,值有三种类型
    pivotY 作为旋转中心的Y的值,值有三种类型
    fromDegrees 动画开始时相较于原始位置所处的角度
    toDegrees 动画结束时相较于原始位置所处的角度, 值为负数时逆时针旋转, 值为正数时顺时针旋转
  2. Scale

    name description
    pivotX 作为动画起始点的X的值,值有三种类型
    pivotY 作为动画起始点Y的值,值有三种类型
    fromXScale 动画开始时X方向相较于原始大小的缩放比例
    toXScale 动画结束时X方向相较于原始大小的缩放比例
    fromYScale 动画开始时Y方向相较于原始大小的缩放比例
    toYScale 动画结束时Y方向相较于原始大小的缩放比例
  3. Translate

    name description
    fromXDelta 动画开始时相较于原始位置X平移的距离,值有三种类型
    toXDelta 动画结束时相较于原始位置X平移的距离,值有三种类型
    fromYDelta 动画开始时相较于原始位置Y平移的距离,值有三种类型
    toYDelta 动画结束时相较于原始位置X平移的距离,值有三种类型
  4. Set

    name description
    shareInterpolator Set动画集合中的动画是否共享插值器, boolean
  • 应用

    1. LayoutAnimation

      name description
      delay 动画延迟播放时间: 用百分号表示基于Item动画的duration,0%,表示动画同步执行; 100% ,表示前一个动画执行完后才执行下一个
      animationOrder 子View动画播放顺序:normal,item的顺序;reverse,item的倒序;random,随机;
      animation 动画
      interpolator 插值器
       layout_animation.xml
          <?xml version="1.0" encoding="utf-8"?>
          <layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
              android:animation="@anim/layout_set_anim"
              android:delay="15%"
              android:animationOrder="normal">
          </layoutAnimation>
      
       layout_set_anim.xml
          <?xml version="1.0" encoding="utf-8"?>
          <set xmlns:android="http://schemas.android.com/apk/res/android"
               android:duration="1000"
          >
          
              <translate
                      android:toXDelta="0%"
                      android:toYDelta="0%"
                      android:fromXDelta="0%"
                      android:fromYDelta="120%"/>
              <alpha
                      android:toAlpha="1.0"
                      android:fromAlpha="0.0"/>
           <!--   <scale
                      android:pivotX="50%"
                      android:pivotY="50%"
                      android:fromXScale="0.2"
                      android:fromYScale="0.2"
                      android:toXScale="1.0"
                      android:toYScale="1.0"/>-->
          
          </set>
      
    2. Activity之间的切换

      • 必须在Activity 的 startActivity 系列方法或finish之后调用
        Activity.overridePendingTransition(enterAnim, exitAnim)
      • 对所有的Activity都有效
        <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
              <!-- Customize your theme here. -->
              <item name="colorPrimary">@color/colorPrimary</item>
              <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
              <item name="colorAccent">@color/colorAccent</item>
              <item name="android:windowAnimationStyle">@style/activityAnimStyle</item>
          </style>
          
        <style name="activityAnimStyle" parent="@android:style/Animation.Activity">
              <item name="android:activityOpenEnterAnimation">@anim/act_next_in</item>
              <item name="android:activityOpenExitAnimation">@anim/act_next_current_out</item>
              <item name="android:activityCloseEnterAnimation">@anim/act_last_in</item>
              <item name="android:activityCloseExitAnimation">@anim/act_last_current_out</item>
          
          </style>
      
    3. Fragment之间的切换

    enterAnim: 指Fragment进入视图时的动画,exitAnim:退出视图时的动画

      FragmentActivity.getSupportFragmentManager()
                      .beginTransaction()
                      {.setCustomAnimations(enterAnim,exitExit) | .setCustomAnimations(enterAnim,exitAnim,popEnterAnim,popExitAnim)}
                      { .add().show() | .replace()}
                      .commit()
    
    

DrawableAnimation(FrameAnimation)

//开始动画
(testV.drawable as? AnimationDrawable)?.start()
  • activity_main.xml

     <?xml version="1.0" encoding="utf-8"?>
        <androidx.constraintlayout.widget.ConstraintLayout
                xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                xmlns:app="http://schemas.android.com/apk/res-auto"
                android:layoutAnimation="@anim/layout_animation"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                tools:context=".MainActivity">
            <androidx.appcompat.widget.Toolbar
                    android:id="@+id/titleToolBar"
                    android:background="@color/colorPrimary"
                    android:layout_width="match_parent"
                    android:minHeight="?android:attr/actionBarSize"
                    app:layout_constraintTop_toTopOf="parent"
                    android:layout_height="wrap_content"/>
            <com.google.android.material.tabs.TabLayout android:layout_width="match_parent"
                                                        app:layout_constraintTop_toBottomOf="@+id/        titleToolBar"
                                                        app:layout_constraintLeft_toLeftOf="parent"
                                                        android:id="@+id/topTab"
                                                        app:tabMode="scrollable"
                                                        android:layout_height="?android:actionBarSize"/>
        
        
            <ImageView
                    android:id="@+id/testV"
                    app:layout_constraintTop_toBottomOf="@+id/topTab"
                    android:layout_width="100dp"
                    android:layout_height="100dp"
                    android:background="#689F38"
                    android:src="@drawable/drawable_animation"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintRight_toRightOf="parent"
                    app:layout_constraintLeft_toLeftOf="parent"
            />
            <ToggleButton
                    android:id="@+id/toggleB"
                    android:textOff="use XML"
                    android:textOn="use JAVA"
                    app:layout_constraintBottom_toBottomOf="parent"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"/>
        
        </androidx.constraintlayout.widget.ConstraintLayout>
        
    
  • AnimationDrawable

        <?xml version="1.0" encoding="utf-8"?>
        <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
                        android:oneshot="false"
        >
            <item android:drawable="@drawable/img_0" android:duration="150"/>
            <item android:drawable="@drawable/img_1" android:duration="150"/>
            <item android:drawable="@drawable/img_2" android:duration="150"/>
            <item android:drawable="@drawable/img_3" android:duration="150"/>
            <item android:drawable="@drawable/img_4" android:duration="150"/>
            <item android:drawable="@drawable/img_5" android:duration="150"/>
            <item android:drawable="@drawable/img_6" android:duration="150"/>
        </animation-list>
    
    

PropertyAnimation

  1. 属性动画不仅仅局限与View,它的作用在于改变目标对象的属性,目标对象不仅是View
  2. View动画只是改变了View的视觉效果,并没有改变View的属性;属性动画则改变了属性。
    如一个用了View动画位移到新位置的按钮,它的点击响应位置还是在原来的位置,本身的属性并没有改变。
    属性动画的点击响应位置则会在新位置(点击响应的位置坐标与组件的位置坐标不是同一个)。
  • ValueAnimator

    1. 普通用法(ofInt(), ofFloat()...)
    • animator_int.xml
        <?xml version="1.0" encoding="utf-8"?>
        <animator xmlns:android="http://schemas.android.com/apk/res/android"
          android:repeatMode="restart"
          android:repeatCount="infinite"
          android:duration="3000"
          android:interpolator="@android:anim/linear_interpolator"
          android:valueType="colorType"
          android:valueFrom="@color/colorFrom"
          android:valueTo="@color/colorTo"
        />
      
    • code
        private val valueAnimator: ValueAnimator
            get() = if (useCode) ValueAnimator.ofInt(Color.parseColor("#008577"), Color.parseColor("#D81B60")).apply {
                repeatCount = ValueAnimator.INFINITE
                repeatMode = ValueAnimator.RESTART
                duration = 3000
                interpolator = AccelerateDecelerateInterpolator()
                addUpdateListener {
                //在回调中改变目标对象相应的属性值,达到动画效果
                    target.background = ColorDrawable(it.animatedValue as Int)
                }
            }
            else (AnimatorInflater.loadAnimator(this, R.animator.animator_int) as ValueAnimator).apply {
                addUpdateListener {
                    target.background = ColorDrawable(it.animatedValue as Int)
                }
            }
            
            //开始动画
            valueAnimator.start()
            //移除更新监听器来结束动画
            valueAnimator.removeUpdateListener(listener)
    
    1. 自定义(ofObject())
      //自定义的Evaluator
        class ScaleShapeEvaluator : TypeEvaluator<ScaleShape> {
            override fun evaluate(fraction: Float, startValue: ScaleShape, endValue: ScaleShape): ScaleShape {
                val x = startValue.x + fraction * (endValue.x - startValue.x)
                val y = startValue.y + fraction * (endValue.y - startValue.y)
        
                return ScaleShape(x, y)
            }
        } 
    
        ValueAnimator.ofObject(ScaleShapeEvaluator(), ScaleShape(0.5F, 0.2F), ScaleShape(2.0F, 3.0F)).apply {
                repeatCount = ValueAnimator.INFINITE
                repeatMode = ValueAnimator.RESTART
                duration = 2000
                interpolator = AccelerateDecelerateInterpolator()
                addUpdateListener(listener)
                start()
            } 
    
  • ObjectAnimator
  1. 普通用法
  • animator_object_rotate.xml

        <?xml version="1.0" encoding="utf-8"?>
        <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
                        android:repeatMode="restart"
                        android:valueFrom="0"
                        android:valueTo="360"
                        android:interpolator="@android:anim/linear_interpolator"
                        android:propertyName="rotationX"
                        android:duration="1000"
                        android:repeatCount="infinite"
                        android:valueType="floatType"
        />
    
    val animator = ObjectAnimator.ofFloat(target, "rotationY", 0f, -360F).apply {
                repeatCount = ObjectAnimator.INFINITE
                repeatMode = ObjectAnimator.RESTART
                duration = 2000
                interpolator = LinearInterpolator()
            }
            or 
    val animator = AnimatorInflater.loadAnimator(this, R.animator.animator_object_rotate)   .apply {
                setTarget(target)
            }
            
    animator.start()       
    //设置目标为null 来取消动画       
    animator.setTarget(null)        
    
  1. 自定义
    对于一些没有的属性,可以通过装饰器模式来包装一下
//ShapeWrapper
class ShapeWrapper(private val target: View) {

    fun setShape(shape: ScaleShape) {
        target.layoutParams.apply {
            width = shape.x.toInt()
            height = shape.y.toInt()
        }
        target.requestLayout()
    }

    fun getShape(): ScaleShape {
        return ScaleShape(target.width.toFloat(), target.height.toFloat())
    }
}
//ScaleShape
data class ScaleShape(var x: Float, var y: Float)
//Evaluator
class ScaleShapeEvaluator : TypeEvaluator<ScaleShape> {
     override fun evaluate(fraction: Float, startValue: ScaleShape, endValue: ScaleShape): ScaleShape {
         val x = startValue.x + fraction * (endValue.x - startValue.x)
         val y = startValue.y + fraction * (endValue.y - startValue.y)

         return ScaleShape(x, y)
     }
}
//使用
val animator = ObjectAnimator.ofObject(
            ShapeWrapper(target),
            "shape",
            ScaleShapeEvaluator(),
            ScaleShape(100F, 100F),
            ScaleShape(500F, 500F)
        ).apply {
            repeatCount = ObjectAnimator.INFINITE
            repeatMode = ObjectAnimator.RESTART
            duration = 2000
            interpolator = LinearInterpolator()
        }

资源

例子

Android开发艺术探索 - 任玉刚

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,252评论 6 516
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,886评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,814评论 0 361
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,869评论 1 299
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,888评论 6 398
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,475评论 1 312
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,010评论 3 422
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,924评论 0 277
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,469评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,552评论 3 342
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,680评论 1 353
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,362评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,037评论 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,519评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,621评论 1 274
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,099评论 3 378
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,691评论 2 361