Android动画(开发艺术探索读书笔记)

Android动画可以分为3类:View动画,帧动画,属性动画

1.View动画

可以通过XML来创建,也可以通过代码来创建

1.1通过XML创建

在res/anim下创建filename.xml文件,语法如下所示

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@[package:]anim/interpolator_resource"
    android:shareInterpolator=["true" | "false"] >
    <alpha
        android:fromAlpha="float"
        android:toAlpha="float" />
    <scale
        android:fromXScale="float"
        android:toXScale="float"
        android:fromYScale="float"
        android:toYScale="float"
        android:pivotX="float"
        android:pivotY="float" />
    <translate
        android:fromXDelta="float"
        android:toXDelta="float"
        android:fromYDelta="float"
        android:toYDelta="float" />
    <rotate
        android:fromDegrees="float"
        android:toDegrees="float"
        android:pivotX="float"
        android:pivotY="float" />
    <set>
        ...
    </set>
</set>

  

View动画不止能够写单个的动画,也可以使用动画集合.<set>代表动画集合(对应于AnimationSet).

1.1.1:interpolator:差值器,可以影响动画的速度。

1.1.2:shareInterpolator是否共享一个差值器,如果集合不指定差值器,子动画就需要指定差值器或者使用默认的差值器。

1.1.3:scale的轴点:pivotX和pivotY

轴点与在中间和在左右2侧的效果是不同的。

1.1.4:duration

1.1.5:fillAfter动画结束后是否停留在结束的位置。

具体例子

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="false"
    >

    <translate
        android:duration="100"
        android:fromXDelta="0"
        android:toXDelta="100"
        android:fromYDelta="0"
        android:toYDelta="100"
        android:interpolator="@android:anim/linear_interpolator"/>

    <rotate
        android:duration="400"
        android:fromDegrees="0"
        android:toDegrees="90"
        />
</set>

使用方式

 Animation animation = AnimationUtils.loadAnimation(AnimationActivity.this, R.anim.filename);
                mButton.startAnimation(animation);

1.2通过代码创建

1.3View动画使用场景

A.ViewGroup子View的出场效果

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:interpolator="@android:anim/accelerate_interpolator"
    android:shareInterpolator="true">

    <alpha
        android:fromAlpha="0.0"
        android:toAlpha="1.0"></alpha>

    <translate
        android:fromYDelta="500"
        android:toYDelta="0"></translate>

</set>

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:delay="0.5"
    android:animationOrder="normal"
    android:animation="@anim/anim_item">
</layoutAnimation>

        Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_item);
        LayoutAnimationController controller = new LayoutAnimationController(animation);
        controller.setDelay(0.5f);
        controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
        v.setLayoutAnimation(controller);

//或者直接在XMl中使用
    <ListView
        android:id="@+id/list"
        android:cacheColorHint="#00000000"
        android:divider="#dddbdb"
        android:dividerHeight="1.0px"
        android:background="#fff4f7f9"
        android:layoutAnimation="@anim/anim_layout"
        android:listSelector="@android:color/transparent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"></ListView>

delay是延时周期(如果周期是300ms延时就是0.5*300=150,第一个是150ms后开始动画,第二个是延时300ms后开始变化,以此类推)

B.Activity之间的切换效果

主要用到了overridePendingTransition这个方法,但是这个方法需要在startActivity之前和finish之后调用才会有效

2.帧动画

3.属性动画

属性动画可以对任意对象的属性进行动画而不仅仅是View,在一定的时间间隔内完对象从一个属性值到另一个属性值得改变,但是属性动画是从Api11才开始有的.

常用的几个类是:ValueAnimator.ObjectAnimator和AnimatorSet其中ObjectAnimator继承自ValueAnimator,AnimatorSet是一个动画集合.可以定义一组动画。

通过代码实现

单个属性与属性集合

    private void startObjectAnimator(View object) {
        ObjectAnimator.ofFloat(object, "translationY", -object.getHeight()).start();

    }

    private void startColorProperty(View view) {
        ValueAnimator colorAnim = ObjectAnimator.ofInt(view, "backgroundColor", 0xFFFF8080,
                0xFF8080FF);
        colorAnim.setDuration(3000);
        colorAnim.setEvaluator(new ArgbEvaluator());
        colorAnim.setRepeatCount(ValueAnimator.INFINITE);
        colorAnim.setRepeatMode(ValueAnimator.REVERSE);
        colorAnim.start();
    }

    private void startSetProperty(View view) {
        AnimatorSet set = new AnimatorSet();
        set.playTogether(
                ObjectAnimator.ofFloat(view, "rotationX", 0, 360),
                ObjectAnimator.ofFloat(view, "rotationY", 0, 360),
                ObjectAnimator.ofFloat(view, "rotation", 0, -90),
                ObjectAnimator.ofFloat(view, "translationX", 0, 90),
                ObjectAnimator.ofFloat(view, "translationY", 0, 90),
                ObjectAnimator.ofFloat(view, "scaleX", 1, 1.5f),
                ObjectAnimator.ofFloat(view, "scaleY", 0, 0.5f),
                ObjectAnimator.ofFloat(view, "alpha", 0, 0.25f, 1)
        );
        set.setDuration(5 * 1000).start();
    }

通过XML定义,属性动画定义在res/animator/下

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="together">

    <objectAnimator
        android:propertyName="x"
        android:duration="300"
        android:valueTo="200"
        android:valueType="intType"></objectAnimator>

    <objectAnimator
        android:propertyName="y"
        android:duration="300"
        android:valueTo="300"
        android:valueType="intType"></objectAnimator>

</set>

加载上面的动画给View

        AnimatorSet animatorSet = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.property_animator);
        animatorSet.setTarget(view);
        animatorSet.start();

理解差值器和估值器

TimeInterpolator翻译成时间差值器,他的作用是根据时间流逝的百分比来计算出当前属性值改变的百分比.

TypeEvaluator的中文翻译是类型估值算法,就是估值器,它的作用是根据当前属性改变的百分比来计算改变后的属性值.

如果需要对其他类型做动画(比如非int,float,color)这时候就需要自定义类型估值算法.

属性动画注意事项:

属性动画要求对象的属性有set和get(可选)方法.

属性动画的监听器

属性动画对于监听动画的过程提供了两个接口AnimatorUpdateListener和AnimatorListener

   public static interface AnimatorListener {
        default void onAnimationStart(Animator animation, boolean isReverse) {
            onAnimationStart(animation);
        }
        default void onAnimationEnd(Animator animation, boolean isReverse) {
            onAnimationEnd(animation);
        }
        void onAnimationStart(Animator animation);
        void onAnimationEnd(Animator animation);
        void onAnimationCancel(Animator animation);
        void onAnimationRepeat(Animator animation);
    }

监听了动画的开始,结束,取消和重复,而且系统提供了AnimatorListenerAdapter这个类,方便我们去继承上面几个方法任意的组合.

    public static interface AnimatorUpdateListener {
        void onAnimationUpdate(ValueAnimator animation);
    }

监听动画的整个过程,动画是由许多帧来组成的,每播放一帧,onAnimatorUpdate就会调用一次.

对任意属性做动画

属性动画是根据外界传递给该属性的初始值和最终值,通过不断的调用set方法,每次传递给set方法的值都不一样,但是越来越接近最终值.这样,对object的abc属性做动画,需要动画生效就需要满足2个条件:

(1):需要提供setAbc()方法,如果做动画的时候没有传递初始值,那么还需要提供getAbc方法,因为系统要去取abc属性的初始值(如果这条不满足,程序直接 Crash).

(2):object的setAbc()方法对属性abc所做的改变必须通过某种方法反映出来,比如会带来UI的改变之类的(如果这条不满足,动画无效但是不会Crash).

对于没有提供get和set方法的属性动画,官方提供了3种解决办法.

对于属性动画的3种解决办法:

1.给你的对象加上get和set方法.

2.采用一个类来包装原始对象,间接为其提供get和set方法.

3.采用ValueAnimator,监听动画过程,自己实现属性的改变.

1.给你的对象加上get和set方法

这种通常对于SDK中的View,是没有权限的.

2.用一个类来包装原始对象,间接为其提供get和set方法.
    private static class ViewWrapper {
        private View mTarget;

        public ViewWrapper(View target) {
            this.mTarget = target;
        }

        public void setWidth(int width) {
            mTarget.getLayoutParams().width = width;
            mTarget.requestLayout();
        }

        public int getWidth() {
            return mTarget.getLayoutParams().width;
        }
    }

    //使用上面的包装类
    ViewWrapper wrapper = new ViewWrapper(view);
    ObjectAnimator.ofInt(wrapper, "width", 500).setDuration(5000).start();

本来想改变Button的width,结果setWidth改变的与我们想要的不是同一个东西,将Button包裹为target,通过改变其LayourParams的width来达到动画的效果.

3.采用ValueAnimator,监听动画过程,自己实现属性的改变.

ValueAnimator本身不作用于任何对象,也就是说直接使用它没有任何效果,可以使用它对一个值做动画,我们对一个值做动画,然后监听它的动画过程,在过程中修改我们动画的属性值.

    private void performAnimator(final View target, final int start, final int end) {
        ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            //估值对象,方便估值的时候使用
            private IntEvaluator mEvaluator = new IntEvaluator();

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //获取当前的进度
                int currentValue = (int) animation.getAnimatedValue();
                float fraction = animation.getAnimatedFraction();
                //重新计算width,然后设置给LayoutParams最后重新绘制
                target.getLayoutParams().width = mEvaluator.evaluate(fraction, start, end);
                target.requestLayout();
            }
        });
        valueAnimator.setDuration(5000).start();
    }

以上就是Android动画的大概内容,其余如属性动画的工作原理,没有讲述.

可能出现的问题:

1.View动画是对View的影像做动画,有时候会出现动画完成了但是View无法隐藏的现象,就是setVisibility(View.GONE)失效了,这时候只要调用view.clearAnimation()清除View动画就可以解决.

2.在进行动画的过程中,尽量使用dp,使用px会导致在不同的设备上有不同的效果.

原文地址:https://www.cnblogs.com/coconna/p/9003080.html

时间: 2024-10-12 01:06:52

Android动画(开发艺术探索读书笔记)的相关文章

Android开发艺术探索读书笔记——进程间通信

1. 多进程使用场景 1) 应用某些模块因为特殊需求需要运行在单独进程中.如消息推送,使消息推送进程与应用进程能单独存活,消息推送进程不会因为应用程序进程crash而受影响. 2) 为加大一个应用可使用的内存,需要多进程来获取多份内存空间. 2. 如何开启多进程 给四大组件(Activity.Service.Receiver.ContentProvider)在AndroidMainfest中指定android:process属性指定. 如果进程以":"开头的进程,代表应用的私有进程,其

android开发艺术探索读书笔记之-------view的事件分发机制

View的点击事件的分发,其实就是对MotionEvent事件的分发过程,即当一个MotionEvent产生后,系统需要把这个事件传递给一个具体的View,而这个过程就是分发过程. 分发过程主要由以下3个方法共同完成: public boolean dispatchTouchEvent(MotionEvent event) 用来进行事件的分发.如果事件能够传递给当前的View,那么此方法一定会被调用,返回结果受当前的View的onTouchEvent和下级View的dispatchTouchEv

Android开发艺术探索(研读笔记)——03-Android中的IPC机制(一)

Android开发艺术探索(研读笔记) 作者:Dimon 微博:@Dimon-喰 GitHub:@Dimon94 LOFTER:@Dimon. 03-Android中的IPC机制(一) 1.Android IPC 简介 IPC(Inter-Process-Communication):含义为进程间通信,指两个进程之间进行数据交换的过程. 什么是进程:一般指一个执行单元,在PC和移动设备上的一个程序或者一个应用. 什么是线程:线程是CPU调度的最小单元,是一种有限的系统资源. 而一个进程可以包含多

Android驱动开发5-8章读书笔记

Android驱动开发读书笔记                                                              第五章 S5PV210是一款32位处理器,具有低功耗的的特点,可为移动设备和一般应用提高性能的微处理器解决方案.它集成了ARM CORTEX-A8核心.实现了ARM架构V7且支持外围设备.他的关键功能是“以带有NEON的cpu子系统为基础的arm”,32/32kb i/d缓存,512kb l2缓存,操作频率800hz为1.1v,1ghz为1.2

Android开发艺术探索读书(三)-View的事件体系

移动手持客户端作为目前最受欢迎的智能设备,拥有着最为广大的体验用户群体.因此,作为软件开发商,要紧紧抓住用户的胃口,不仅要向用户提供合适的服务项目,也应该更为注重与用户的交互体验.而作为感觉型的用户,应用操作是否流畅,界面内容是不是足够精致,是判断该应用是不是一个好应用的硬性标准.那么,要如何去强化与用户的交互体验呢?这就涉及了本章所讲的内容:View的事件体系 提纲: 一.什么是View 二.View的位置参数 三.几个相关的View知识点 四.View的滑动深入 五.view的事件分发 六.

Android开发艺术探索学习笔记(十一)

第十一章  Android的线程和线程池 从用途上来说,线程分为子线程和主线程,主线程主要处理和界面相关的事情,而子线程往往用于执行耗时的操作.AsyncTask,IntentService,HandlerThread都可以扮演线程的角色. AsyncTask封装了线程池和Handler,主要是为了方便开发者在主线程中更新UI. HandlerThread是一种具有消息循环的线程,在它的内部可以使用Handler. IntentService是一个服务,系统对其进行了封装,使其可以更方便的执行后

《Android 开发艺术探索》笔记——(3)View 的事件体系

View 基础知识 View 是 Android 中所有控件的基类,ViewGroup 也继承了 View. Android 中,x 轴和 y 轴的正方向分别为右和下. 位置参数: (left , top ): View 左上角原始坐标 (right, bottom): View 右下角原始坐标 (x , y ): View 左上角最终坐标 translationX: View 左上角横向偏移量 translationY: View 左上角纵向偏移量 x = left + translation

《android开发艺术探索》读书笔记(五)--动画

接上篇<android开发艺术探索>读书笔记(五)--Drawable No1: 自定义动画:派生一种新动画只需要继承Animation这个抽象类,然后重写它的initialize和applyTransformation方法,在initialize方法中做一些初始化工作,在applyTransformation中进行相应的矩阵变换即可,很多时候需要采用Camera来简化矩阵变换的过程. No2: 属性动画PropertyAnimation 补间动画TweenAnimation 帧动画Frame

《android开发艺术探索》读书笔记(十五)--Android性能优化

接上篇<android开发艺术探索>读书笔记(十四)--JNI和NDK编程 No1: 如果<include>制定了这个id属性,同时被包含的布局文件的根元素也制定了id属性,那么以<include>指定的id属性为准 No2: 绘制优化 1)onDraw中不要创建新的局部对象 2)onDraw方法中不要做耗时的任务 No3: 内存泄露优化 场景一:静态变量导致的内存泄露: 如果静态变量持有了一个Activity,会导致Activity无法及时释放. 解决办法:1使用Ap