Android 动画学习

Android 按动画类型划分为两类:

  • View Animation
    • Tween Animation
      又称“补间动画”,较老的动画系统,常用来制作图片的一些特效(渐变、平移、缩放、旋转),适用于View对象
    • Frame Animation
      又称“帧动画”,就是一系列图片按照顺序播放形成动画
  • Property Animation
    属性动画,Android 3.0(api 11)之后引入,与前两者不同是改变对象属性值赖达到动画效果

Property Animation与Tween Animation 之间的区别

Property Animation:更改的是对象的实际属性
Tween Animation:更改的是View的绘制效果,对象的属性值是不会改变的

Property Animation 主要类图

Android 动画学习_第1张图片

Property Animation 工作方式

要启动动画,首先创建一个 ValueAnimator或其子类并指定要动画显示的属性的初始值、结束值以及显示时间,然后调用 start() 启动动画。在整个动画过程中, ValueAnimator 根据动画总时间和已进行的时间自动计算出一个时间比例因子(elapsed fraction),大小介于0和1之间。 时间比例因子代表动画已完成时间的百分比,0 表示 0%,1 表示 100%。ValueAnimator 算完时间比例因子后,将调用已设置好的 TimeInterpolator 计算出一个插值因子(interpolated fraction)。插值因子是一个由时间比例因子换算出来的图像显示状态因子。算完插值因子, ValueAnimator 就会调用合适的 TypeEvaluator ,根据插值因子、初始值、结束值计算出需要动画显示的属性值。计算出属性值后,最后为需要执行动画的对象设置对应属性的属性值。动画在持续的整个过程中,会根据我们当初设置的TimeInterpolator 和TypeEvaluator的计算方式计算出的不同的属性值,从而不断地改变对象属性值的大小,进而产生各式各样的动画效果。

Android 动画学习_第2张图片
转自:Android 动画学习(二)之Property Animation初步介绍

Property Animation 使用方法

ValueAnimator是Property Animation系统的核心类,它包含了配置Property Animation属性的大部分方法,那要实现一个Property Animation,都需要直接或间接使用ValueAnimator类。

那一般使用ValueAnimator实现动画分为以下七个步骤:
1. 调用ValueAnimation类中的ofInt(int…values)、ofFloat(String propertyName,float…values)等静态方法实例化ValueAnimator对象,并设置目标属性的属性名、初始值或结束值等值;
2.调用addUpdateListener(AnimatorUpdateListener mListener)方法为ValueAnimator对象设置属性变化的监听器;
3.创建自定义的Interpolator,调用setInterpolator(TimeInterpolator value)为ValueAniamtor设置自定义的Interpolator;(可选,不设置默认为缺省值)
4.创建自定义的TypeEvaluator,调用setEvaluator(TypeEvaluator value)为ValueAnimator设置自定义的TypeEvaluator;(可选,不设置默认为缺省值)
5.在AnimatorUpdateListener 中的实现方法为目标对象的属性设置计算好的属性值。
6.设置动画的持续时间、是否重复及重复次数等属性;
7.为ValueAnimator设置目标对象并开始执行动画。

   /** * 使用ValueAnimator改变Imageview的margin的值 */    public void marginValueAnimator(){        //1.调用ofInt(int...values)方法创建ValueAnimator对象        ValueAnimator mAnimator = ValueAnimator.ofInt(0,screenWidth - mImageViewTest.getWidth());        //2.为目标对象的属性变化设置监听器        mAnimator.addUpdateListener(new AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                // 3.为目标对象的属性设置计算好的属性值                int animatorValue = (int)animation.getAnimatedValue();                MarginLayoutParams marginLayoutParams = (MarginLayoutParams) mImageViewTest.getLayoutParams();                marginLayoutParams.leftMargin = animatorValue;                mImageViewTest.setLayoutParams(marginLayoutParams);            }        });        //4.设置动画的持续时间、是否重复及重复次数等属性        mAnimator.setDuration(2000);        mAnimator.setRepeatCount(3);        mAnimator.setRepeatMode(ValueAnimator.REVERSE);        //5.为ValueAnimator设置目标对象并开始执行动画        mAnimator.setTarget(mImageViewTest);        mAnimator.start();    }

使用ObjectAnimator实现动画
我们接着学习一个比较重要的动画实现类–ObjectAnimator。该类作为ValueAnimator的子类不仅继承了ValueAnimator的所有方法和特性,并且还封装很多实用的方法,方便开发人员快速实现动画。同时,由于属性值会自动更新,使用ObjectAnimator实现动画不需要像ValueAnimator那样必须实现 ValueAnimator.AnimatorUpdateListener ,因此实现任意对象的动画显示就更加容易了。我们在大部分的开发工作中,都会使用ObjectAnimator而非ValueAnimator实现我们所需的动画效果。
前几篇博文我们都介绍了View Animation,我们了解了其实现View对象动画的特点,即View Animation本身是通过改变View的绘制方式来实现动画的,View对象本身的属性值并没有改变,对象仍然停留在原始位置。那Android为了消除这一弊病,在 Android 3.0 中给 View 增加了一些新的属性以及相应的 getter、setter 方法。Property Animation系统可以通过修改 View 对象实际的属性值来实现屏幕上的动画效果。此外,当属性值发生变化时,Views 也会自动调用 invalidate() 方法来刷新屏幕。 View 类中新增的便于实现 property 动画的属性包括:
(1) translationX 和 translationY:这两个属性控制着 View 的屏幕位置坐标变化量,以 layout 容器的左上角为坐标原点;
(2) rotation、rotationX 和 rotationY:这三个属性控制着 2D 旋转角度(rotation属性)和围绕某枢轴点的 3D 旋转角度;
(3) scaleX、scaleY:这两个属性控制着 View 围绕某枢轴点的 2D 缩放比例;
(4) pivotX 和 pivotY: 这两个属性控制着枢轴点的位置,前述的旋转和缩放都是以此点为中心展开的,缺省的枢轴点是 View 对象的中心点;
(5) x 和 y:这是指 View 在容器内的最终位置,等于 View 左上角相对于容器的坐标加上 translationX 和 translationY 后的值;
(6)alpha:表示 View 的 alpha 透明度。缺省值为 1 (不透明),为 0 则表示完全透明(看不见);
要动画显示 View 对象的某个属性,比如颜色或旋转值,我们所有要做的事情就是创建一个 Property animation,并设定对应的 View 属性。那接下来我们就用ObjectAnimator类来分别实现View的透明度渐变、收缩、移动和旋转等动画效果,那在此之前我们也来总结下使用ObjectAnimator实现动画的几个步骤,如下:
1.通过调用ofFloat()、ofInt()等方法创建ObjectAnimator对象,并设置目标对象、需要改变的目标属性名、初始值和结束值;
2.设置动画的持续时间、是否重复及重复次数等属性;
3.启动动画。
转自:Android动画学习(三)之使用ValueAnimator和ObjectAnimator实现动画实例

    public class ObjectAnimatorFragment extends Fragment implements OnClickListener{    private ListView mListViewFront;    private ListView mListViewReverse;    private Button mButtonFlip;    private Button mButtonAlpha;    private Button mButtonScale;    private Button mButtonTranslate;    private Button mButtonRotate;    private Button mButtonSet;    private ImageView mImageView;    private int screenWidth = 0;    private int screenHeight = 0;    String[] frontStrs = {            "Front Page 1",            "Front Page 2",            "Front Page 3",            "Front Page 4",            "Front Page 5",            "Front Page 6",    };    String[] reverseStrs = {            "Reverse Page 1",            "Reverse Page 2",            "Reverse Page 3",            "Reverse Page 4",            "Reverse Page 5",            "Reverse Page 6",    };    @Override    public void onActivityCreated(Bundle savedInstanceState) {        // TODO Auto-generated method stub        super.onActivityCreated(savedInstanceState);        DisplayMetrics metrics = new DisplayMetrics();        getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);        float density = metrics.density;        //screenWidth = (int)(metrics.widthPixels * density + 0.5f);        //screenHeight = (int)(metrics.heightPixels * density + 0.5f);        screenWidth = metrics.widthPixels;        screenHeight = metrics.heightPixels;    }    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container,            Bundle savedInstanceState) {        // TODO Auto-generated method stub        View rootView = inflater.inflate(R.layout.fragment_objectanimator, container, false);        mListViewFront = (ListView) rootView.findViewById(R.id.front_page_listview);        mListViewReverse = (ListView) rootView.findViewById(R.id.reverse_page_listview);        mButtonFlip = (Button)rootView.findViewById(R.id.button_flip);        mButtonFlip.setOnClickListener(this);        mButtonAlpha = (Button)rootView.findViewById(R.id.button_alpha);        mButtonAlpha.setOnClickListener(this);        mButtonScale = (Button)rootView.findViewById(R.id.button_scale);        mButtonScale.setOnClickListener(this);        mButtonTranslate = (Button)rootView.findViewById(R.id.button_translate);        mButtonTranslate.setOnClickListener(this);        mButtonRotate = (Button)rootView.findViewById(R.id.button_rotate);        mButtonRotate.setOnClickListener(this);        mButtonSet = (Button)rootView.findViewById(R.id.button_set);        mButtonSet.setOnClickListener(this);        mImageView = (ImageView)rootView.findViewById(R.id.objectanimator_imageview);        mImageView.setOnClickListener(this);        initData();        return rootView;    }    public void initData(){        ArrayAdapter<String> frontListData = new ArrayAdapter<String>(getActivity(), R.layout.layout_objectanimator_item,R.id.objectanimtor_item_textview, frontStrs);        ArrayAdapter<String> reverseListData = new ArrayAdapter<String>(getActivity(), R.layout.layout_objectanimator_item,R.id.objectanimtor_item_textview, reverseStrs);        mListViewFront.setAdapter(frontListData);        mListViewReverse.setAdapter(reverseListData);        mListViewReverse.setRotationX(-90.0f);    }    @Override    public void onPause() {        // TODO Auto-generated method stub        super.onPause();    }    @Override    public void onClick(View v) {        // TODO Auto-generated method stub        switch (v.getId()) {        case R.id.button_flip:            flip();            break;        case R.id.button_alpha:            alphaAnimator();            break;        case R.id.button_scale:            scaleAnimator();            break;        case R.id.button_translate:            translateAniamtor();            break;        case R.id.button_rotate:            rotateAniamtor();            break;        case R.id.button_set:            setAnimator();            break;        case R.id.objectanimator_imageview:            mListViewFront.setVisibility(View.VISIBLE);            mImageView.setVisibility(View.GONE);            break;        default:            break;        }    }    /** * 翻转动画效果 */    public void flip(){        final ListView visibleView;        final ListView invisibleView;        if(mListViewFront.getVisibility() == View.GONE){            visibleView = mListViewReverse;            invisibleView = mListViewFront;        }else{            visibleView = mListViewFront;            invisibleView = mListViewReverse;        }        //创建ListView从Visible到Gone的动画        ObjectAnimator visibleToInVisable = ObjectAnimator.ofFloat(visibleView, "rotationX", 0.0f,90.0f);        //设置插值器        visibleToInVisable.setInterpolator(new AccelerateInterpolator());        visibleToInVisable.setDuration(500);        //创建ListView从Gone到Visible的动画        final ObjectAnimator invisibleToVisible = ObjectAnimator.ofFloat(invisibleView, "rotationX", -90.0f,0.0f);        //设置插值器        invisibleToVisible.setInterpolator(new DecelerateInterpolator());        invisibleToVisible.setDuration(500);        visibleToInVisable.addListener(new AnimatorListenerAdapter() {            @Override            public void onAnimationEnd(Animator animation) {                // TODO Auto-generated method stub                super.onAnimationEnd(animation);                visibleView.setVisibility(View.GONE);                invisibleToVisible.start();                invisibleView.setVisibility(View.VISIBLE);            }        });        visibleToInVisable.start();    }    /** * 渐变动画效果 */    public void alphaAnimator(){        ListView alphaListView = null;        if(mListViewFront.getVisibility() == View.GONE){            alphaListView = mListViewReverse;        }else{            alphaListView = mListViewFront;        }        //1、通过调用ofFloat()方法创建ObjectAnimator对象,并设置目标对象、需要改变的目标属性名、初始值和结束值;        ObjectAnimator mAnimatorAlpha = ObjectAnimator.ofFloat(alphaListView, "alpha", 1.0f,0.0f);        //2、设置动画的持续时间、是否重复及重复次数属性;        mAnimatorAlpha.setRepeatMode(Animation.REVERSE);        mAnimatorAlpha.setRepeatCount(3);        mAnimatorAlpha.setDuration(1000);        //3、启动动画        mAnimatorAlpha.start();    }    /** * 伸缩动画效果 */    public void scaleAnimator(){        ListView scaleListView = null;        if(mListViewFront.getVisibility() == View.GONE){            scaleListView = mListViewReverse;        }else{            scaleListView = mListViewFront;        }        ObjectAnimator mAnimatorScaleX = ObjectAnimator.ofFloat(scaleListView, "scaleX", 1.0f,0.0f);        mAnimatorScaleX.setRepeatMode(Animation.REVERSE);        mAnimatorScaleX.setRepeatCount(3);        mAnimatorScaleX.setDuration(1000);        ObjectAnimator mAnimatorScaleY = ObjectAnimator.ofFloat(scaleListView, "scaleY", 1.0f,0.0f);        mAnimatorScaleY.setRepeatMode(Animation.REVERSE);        mAnimatorScaleY.setRepeatCount(3);        mAnimatorScaleY.setDuration(1000);        mAnimatorScaleX.start();        mAnimatorScaleY.start();    }    /** * 位移动画效果 */    public void translateAniamtor(){        ListView translateListView = null;        if(mListViewFront.getVisibility() == View.GONE){            translateListView = mListViewReverse;        }else{            translateListView = mListViewFront;        }        ObjectAnimator mAnimatorTranslateX = ObjectAnimator.ofFloat(translateListView, "translationX", 0.0f,screenWidth/2);        mAnimatorTranslateX.setRepeatMode(Animation.REVERSE);        mAnimatorTranslateX.setRepeatCount(3);        mAnimatorTranslateX.setDuration(1000);        ObjectAnimator mAnimatorTranslateY = ObjectAnimator.ofFloat(translateListView, "translationY", 0.0f,screenHeight/2);        mAnimatorTranslateY.setRepeatMode(Animation.REVERSE);        mAnimatorTranslateY.setRepeatCount(3);        mAnimatorTranslateY.setDuration(1000);        mAnimatorTranslateX.start();        mAnimatorTranslateY.start();    }    /** * 旋转动画效果 */    public void rotateAniamtor(){        ListView rotateListView = null;        if(mListViewFront.getVisibility() == View.GONE){            rotateListView = mListViewReverse;        }else{            rotateListView = mListViewFront;        }        ObjectAnimator mAnimatorRotate = ObjectAnimator.ofFloat(rotateListView, "rotation", 0.0f,360.0f);        mAnimatorRotate.setRepeatMode(Animation.REVERSE);        mAnimatorRotate.setRepeatCount(2);        mAnimatorRotate.setDuration(2000);        mAnimatorRotate.start();    }    /** * 动画集合 */    public void setAnimator(){        ListView setListView = null;        if(mListViewFront.getVisibility() == View.GONE){            setListView = mListViewReverse;        }else{            setListView = mListViewFront;        }        setListView.setVisibility(View.GONE);        if(mImageView.getVisibility() == View.GONE){            mImageView.setVisibility(View.VISIBLE);        }        //代码方式设置动画        codeAnimatorSet(mImageView);        //用ViewPropertyAnimator实现动画        //viewPropertyAnimator(setListView);        //加载XML文件中的动画        /*AnimatorSet mAnimatorSet = (AnimatorSet) AnimatorInflater.loadAnimator(getActivity(), R.animator.property_animation_animatorset); mAnimatorSet.setTarget(mImageView); mAnimatorSet.start();*/    }    /** * 使用编码方式实现动画效果 * @param mImageView */    public void codeAnimatorSet(ImageView mImageView){        AnimatorSet mAnimatorSet = new AnimatorSet();        ObjectAnimator mAnimatorSetRotateX = ObjectAnimator.ofFloat(mImageView, "rotationX", 0.0f,360.0f);        mAnimatorSetRotateX.setDuration(3000);        ObjectAnimator mAnimatorSetRotateY = ObjectAnimator.ofFloat(mImageView, "rotationY", 0.0f,360.0f);        mAnimatorSetRotateY.setDuration(3000);        ObjectAnimator mAnimatorScaleX = ObjectAnimator.ofFloat(mImageView, "scaleX", 1.0f,0.5f);        mAnimatorScaleX.setRepeatCount(1);        mAnimatorScaleX.setRepeatMode(Animation.REVERSE);        mAnimatorScaleX.setDuration(1500);        ObjectAnimator mAnimatorScaleY = ObjectAnimator.ofFloat(mImageView, "scaleY", 1.0f,0.5f);        mAnimatorScaleY.setRepeatCount(1);        mAnimatorScaleY.setRepeatMode(Animation.REVERSE);        mAnimatorScaleY.setDuration(1500);        mAnimatorSet.play(mAnimatorSetRotateY).with(mAnimatorScaleX);        mAnimatorSet.play(mAnimatorScaleX).with(mAnimatorScaleY);        mAnimatorSet.play(mAnimatorSetRotateY).before(mAnimatorSetRotateX);        mAnimatorSet.start();    }    public void viewPropertyAnimator(ListView mListViewHolder){        mListViewHolder.animate().cancel();        mListViewHolder.animate().rotationX(360.0f).setDuration(3000).start();    }}

作为记录学习,多数内容转自:yegongheng的blog

更多相关文章

  1. Android 布局文件属性讲解
  2. Android工作学习笔记之图片自适应imageview属性android:scaleTyp
  3. Android 复习笔记之图解View类的XML属性、相关方法及说明
  4. Android 开发者 for Flutter (3) flutter中动画是如何实现的 及 如
  5. android过渡动画之makeSceneTransitionAnimation学习笔记

随机推荐

  1. C语言之库函数的模拟与使用
  2. 【等待事件】等待事件概述(1)--等待事件的
  3. C语言实战小项目——通讯录1.0
  4. C语言进阶(一)---数据的存储
  5. C语言指针全归纳-初级版
  6. 【方法】Oracle用户密码含特殊字符时的登
  7. C语言进阶(二)--- 整型存放练习
  8. 【DB笔试面试732】在Oracle中,Oracle Clus
  9. C语言实现计算器
  10. C语言编程笔试题(一)