介绍

动画是Android运用中不可或缺的一部分,它能够让运用愈加生动、风趣,还能够提升用户体会。Android供给了多种动画完成办法,在本文中,咱们将深入研究Android动画的方方面面。从根本的View动画和特点动画开始。咱们将介绍高档动画技巧,包含运用自界说插值器、完成杂乱作用,以及功能优化的最佳实践。

Android动画根底

Android动画体系供给了两种首要类型的动画:View动画和特点动画。这两种动画类型分别适用于不同的场景,但都为开发者供给了丰厚的选项来创造各种令人形象深入的用户界面作用。

View动画

  1. 补间动画

    补间动画是指在动画开始和完毕时只关怀动画的起始状况和完毕状况,而不关怀中间的进程。在Android中,常见的补间动画包含平移、缩放、旋转和透明度改动。下面是一个简略的平移动画示例:

    // 创立一个平移动画,将View从当前位置移动到x=200的位置
    val translateAnimation = TranslateAnimation(0f, 200f, 0f, 0f)
    translateAnimation.duration = 1000 // 动画持续时刻为1秒
    // 将动画运用到View
    view.startAnimation(translateAnimation)
    
  2. 逐帧动画

    逐帧动画是经过一系列预先界说好的图片(帧)连续播映,构成动画作用。在Android中,通常运用XML资源文件界说逐帧动画。以下是一个简略的逐帧动画XML文件:

    <!-- res/anim/frame_animation.xml -->
    <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
        android:oneshot="false">
        <item android:drawable="@drawable/frame1" android:duration="100" />
        <item android:drawable="@drawable/frame2" android:duration="100" />
        <item android:drawable="@drawable/frame3" android:duration="100" />
        <!-- 增加更多帧... -->
    </animation-list>
    

    在代码中加载并运用逐帧动画:

    // 加载逐帧动画
    val frameAnimation = AnimationUtils.loadAnimation(context, R.anim.frame_animation)
    // 将动画运用到ImageView
    imageView.startAnimation(frameAnimation)
    

特点动画

特点动画答应对视图的任何特点进行平滑的动画变换,包含自界说特点。它供给了更灵敏的办法来完成杂乱的动画作用,并经过ObjectAnimator类完成。

  1. 值动画(ValueAnimator)

    值动画答应咱们在必定时刻范围内逐步改动某个值,能够用于完成更杂乱的动画作用。以下是一个简略的值动画示例,完成一个色彩过渡:

    // 创立一个值动画,逐步改动背景色彩从红色到蓝色
    val colorAnimator = ValueAnimator.ofArgb(Color.RED, Color.BLUE)
    colorAnimator.duration = 2000 // 动画持续时刻为2秒
    // 增加值动画的监听器,实时更新背景色彩
    colorAnimator.addUpdateListener { animator ->
        val color = animator.animatedValue as Int
        view.setBackgroundColor(color)
    }
    // 发动值动画
    colorAnimator.start()
    
  2. 方针动画(ObjectAnimator)

    方针动画是值动画的扩展,它不只能够改动根本数据类型的值,还能够改动方针的特点。以下是一个简略的方针动画示例,旋转一个ImageView:

    // 创立一个方针动画,逐步旋转ImageView的视点
    val rotateAnimator = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 360f)
    rotateAnimator.duration = 1000 // 动画持续时刻为1秒
    // 发动方针动画
    rotateAnimator.start()
    

特点动画原理

特点动画的完成原理是经过PropertyValuesHolder来描绘特点值的改动。PropertyValuesHolder能够描绘一个或多个特点值的改动,每个特点值的改动能够是一个线性改动、一个非线性改动或一个关键帧改动。

PropertyValuesHolder的构造办法如下:

fun PropertyValuesHolder(propertyName: String, valueToInterpolate: Float): PropertyValuesHolder {
    return PropertyValuesHolder(propertyName).apply {
        setFloatValues(valueToInterpolate)
    }
}

其间,propertyName是特点名称,valueToInterpolate是特点值。

PropertyValuesHolder能够经过setFloatValues()办法来设置多个特点值,也能够经过setKeyframe()办法来设置关键帧。

PropertyValuesHoldersetFloatValues()办法的运用示例如下:

val alphaHolder = PropertyValuesHolder.ofFloat("alpha", 0.0f, 1.0f)

该代码创立了一个alphaHolder方针,它描绘了控件的alpha特点从0.0f到1.0f的线性改动。

PropertyValuesHoldersetKeyframe()办法的运用示例如下:

val alphaHolder = PropertyValuesHolder.ofFloat("alpha")
alphaHolder.setKeyframe(0.0f, 0.0f)
alphaHolder.setKeyframe(0.5f, 0.5f)
alphaHolder.setKeyframe(1.0f, 1.0f)

该代码创立了一个alphaHolder方针,它描绘了控件的alpha特点从0.0f到1.0f的非线性改动。

PropertyValuesHolder创立完成后,就能够将其增加到ObjectAnimator方针中来创立动画了。

ObjectAnimator的构造办法如下:

fun ObjectAnimator(target: Any, propertyName: String, propertyValuesHolder: PropertyValuesHolder): ObjectAnimator {
    return ObjectAnimator().apply {
        setTarget(target)
        setProperty(propertyName)
        setPropertyValuesHolder(propertyValuesHolder)
    }
}

其间,target是动画的方针方针,propertyName是特点名称,propertyValuesHolder是特点值的描绘方针。

插值器

插值器能够改动动画的履行速率,让动画作用愈加生动、风趣。Android供给了多种插值器,能够满足不同的需求。

  1. 体系内置插值器

    以下是一些常用的体系内置插值器:

    • AccelerateDecelerateInterpolator: 先加快后减速的插值器。
    • AccelerateInterpolator: 先加快后匀速的插值器。
    • DecelerateInterpolator: 先减速后匀速的插值器。
    • LinearInterpolator: 线性匀速的插值器。
    // 运用体系内置插值器的例子,完成先加快后减速的动画
    val scaleAnimator = ObjectAnimator.ofFloat(view, "scaleX", 0.5f, 2f)
    scaleAnimator.duration = 1000
    scaleAnimator.interpolator = AccelerateDecelerateInterpolator()
    scaleAnimator.start()
    
  2. 自界说插值器

    对于特定的动画作用,咱们还能够创立自界说插值器。自界说插值器需求完成 Interpolator 接口。以下是一个简略的自界说插值器的示例,完成先减速后加快的作用:

    class DecelerateAccelerateInterpolator : Interpolator {
        override fun getInterpolation(input: Float): Float {
            // 运用数学函数完成先减速后加快的插值器
            return Math.cos((input + 1) * Math.PI).toFloat() / 2.0f + 0.5f
        }
    }
    
    // 运用自界说插值器的例子,完成先减速后加快的动画
    val rotateAnimator = ObjectAnimator.ofFloat(view, "rotation", 0f, 360f)
    rotateAnimator.duration = 1000
    rotateAnimator.interpolator = DecelerateAccelerateInterpolator()
    rotateAnimator.start()
    

运用估值器

估值器能够让动画愈加精准、灵敏。估值器能够将特点值的改动从线性改动转换为非线性改动。

ObjectAnimator方针的setEvaluator()办法能够设置估值器。

setEvaluator()办法的运用示例如下:

val objectAnimator = ObjectAnimator.ofFloat(button, "alpha", 0.0f, 1.0f)
objectAnimator.setEvaluator(ArgbEvaluator()())

运用关键帧

关键帧能够让动画愈加杂乱、多样。关键帧能够指定动画在特定时刻点的特点值。

PropertyValuesHolder方针的setKeyframe()办法能够设置关键帧。

setKeyframe()办法的运用示例如下:

val alphaHolder = PropertyValuesHolder.ofFloat("alpha")
alphaHolder.setKeyframe(0.0f, 0.0f)
alphaHolder.setKeyframe(0.5f, 0.5f)
alphaHolder.setKeyframe(1.0f, 1.0f)

该代码创立了一个alphaHolder方针,它描绘了控件的alpha特点从0.0f到1.0f的非线性改动。

运用动画组合

动画组合能够让动画愈加丰厚、生动。动画组合能够将多个动画组合在一同,构成一个杂乱的动画作用。

AnimatorSet类能够用于创立动画组合。

AnimatorSet的构造办法如下:

fun AnimatorSet(): AnimatorSet {
    return AnimatorSet()
}

AnimatorSet方针能够经过play()办法来增加动画。

play()办法的运用示例如下:

val objectAnimator1 = ObjectAnimator.ofFloat(button, "alpha", 0.0f, 1.0f)
val objectAnimator2 = ObjectAnimator.ofFloat(button, "translationX", 0f, 100f)
val animatorSet = AnimatorSet()
animatorSet.playTogether(objectAnimator1, objectAnimator2)
animatorSet.duration = 2000
animatorSet.start()

该代码创立了一个动画组合,它将按钮的alpha特点从0.0f变为1.0f,并将按钮的translationX特点从0f变为100f。

运用动画监听器

动画监听器能够让开发者在动画的不同阶段进行监听和操作。动画监听器能够监听动画的开始、完毕、重复、撤销等事情。

ObjectAnimator方针的addListener()办法能够增加动画监听器。

addListener()办法的运用示例如下:

val objectAnimator = ObjectAnimator.ofFloat(button, "alpha", 0.0f, 1.0f)
objectAnimator.addListener(object : Animator.AnimatorListener {
    override fun onAnimationStart(animation: Animator) {
        // 动画开始时履行的操作
    }
    override fun onAnimationEnd(animation: Animator) {
        // 动画完毕时履行的操作
    }
    override fun onAnimationCancel(animation: Animator) {
        // 动画撤销时履行的操作
    }
    override fun onAnimationRepeat(animation: Animator) {
        // 动画重复时履行的操作
    }
})
objectAnimator.start()

功能优化与最佳实践

内存办理与动画

  1. 运用ViewPropertyAnimator

    ViewPropertyAnimator 是一种轻量级的动画体系,它在大多数情况下都比传统的特点动画更高效。运用 ViewPropertyAnimator 能够防止创立很多的临时方针,然后减小内存占用。

    // 运用ViewPropertyAnimator的例子
    view.animate()
        .translationX(200f)
        .setDuration(1000)
        .start()
    
  2. 防止运用大型位图

    在动画中运用大型位图或许会导致内存占用过高,引起功能问题。能够考虑运用矢量图或适当紧缩和缩放位图。

GPU过度制作的处理

  1. 运用HardwareLayer

    将动画方针的视图标记为硬件层能够减少过度制作,进步功能。在动画开始前将视图设置为硬件层,动画完毕后清除硬件层。

    // 将View标记为硬件层
    view.setLayerType(View.LAYER_TYPE_HARDWARE, null)
    // 在动画完毕后清除硬件层
    translateAnimator.addListener(object : AnimatorListenerAdapter() {
        override fun onAnimationEnd(animation: Animator?) {
            view.setLayerType(View.LAYER_TYPE_NONE, null)
        }
    })
    
  2. 运用View.setWillNotDraw(true)

    假如视图不需求手动制作内容,能够经过 setWillNotDraw(true) 来防止触发不必要的制作操作。

    // 在View初始化时设置
    view.setWillNotDraw(true)
    

硬件加快与动画功能

启用硬件加快能够进步动画功能,但在某些情况下或许导致问题。保证测试硬件加快对运用功能的影响,并根据需求进行调整。

// 在AndroidManifest.xml中启用硬件加快
<application android:hardwareAccelerated="true">
   <!-- ... -->
</application>

功能建议

  1. 防止过多的图层叠加:减少视图层级,降低过度制作的或许性。
  2. 运用HandlerRunnable进行动画更新
  3. 防止在onDraw办法中履行杂乱的计算:这或许导致界面卡顿。
  4. 运用简略的插值器或估值器。

总结

Android动画是每一个开发者必备的技能,它具有简略易用、灵敏性强等长处。经过把握特点动画的原理和高档技巧,能够让开发者创立出愈加丰厚、生动的动画作用。

引荐

android_startup: 供给一种在运用发动时能够愈加简略、高效的办法来初始化组件,优化发动速度。不只支撑Jetpack App Startup的全部功能,还供给额定的同步与异步等待、线程控制与多进程支撑等功能。

AwesomeGithub: 根据Github的客户端,纯练习项目,支撑组件化开发,支撑账户暗码与认证登陆。运用Kotlin言语进行开发,项目架构是根据JetPack&DataBinding的MVVM;项目中运用了Arouter、Retrofit、Coroutine、Glide、Dagger与Hilt等盛行开源技能。

flutter_github: 根据Flutter的跨渠道版本Github客户端,与AwesomeGithub相对应。

android-api-analysis: 结合详细的Demo来全面解析Android相关的知识点, 帮助读者能够更快的把握与了解所阐述的关键。

daily_algorithm: 每日一算法,由浅入深,欢迎参加一同共勉。