美文网首页
属性动画

属性动画

作者: AJoyce_ | 来源:发表于2016-10-17 10:07 被阅读665次
Android提供了几种动画:View Animation 、Drawable Animation 、Property Animation。其中View Animation只支持简单的平移,旋转,缩放,不透明度;Drawable Animation也就是帧动画,通过图片的切换来达到动画的效果,有点像Gif格式的图片。有时候,这些都不能满足我们的需求,在Android3.0的时候系统为我们提供了一种全新的动画模式——属性动画(Property animation)。本文说说属性动画的具体实现,重点讲数字动画;涉及到的相关类及用法请自行Google。
效果图:
数字动画.gif
原理:

属性动画要求动画作用的对象提供该属性的get和set方法,属性动画根据你传递的该熟悉的初始值和最终值,以动画的效果多次去调用set方法,每次传递给set方法的值都不一样,确切来说是随着时间的推移,所传递的值越来越接近最终值。总结一下,你对object的属性xxx做动画,如果想让动画生效,要同时满足两个条件:

  • object必须要提供setXxx方法,如果动画的时候没有传递初始值,那么还要提供getXxx方法,因为系统要去拿xxx属性的初始值(如果这条不满足,程序直接Crash)。
  • object的setXxx对属性xxx所做的改变必须能够通过某种方法反映出来,比如会带来ui的改变啥的(如果这条不满足,动画无效果但不会Crash)。

那如果对象没有此属性,而我们又要实现这样的效果怎么办呢? 就像数字动画,TextView没有为我们提供number属性,正在我愁眉苦脸时,Google给了我们三种解决方案。

方案一:给你的对象加上get和set方法,如果你有权限的话

如果你有权限的话,加上get和set就搞定了,但是很多时候我们没权限去这么做,无法修改Android SDK内部的实现。这个方法最简单,但是往往是不可行的,那我们在此演示一下Android SDK内部本来就提供了set/get方法的如何去实现。

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    android:alpha="0.4" > //不透明度属性

一般情况只要对象有此属性就可以实现此属性的动画,比如LinearLayout的属性alpha,就可以实现不透明度动画,同样也可以用background来实现背景的动画。
ObjectAnimator常用方法有:ofFloat(),ofInt(),ofObject(),ofArgb(),ofPropertyValuesHolder()。

private void displayAnimation() {
    ObjectAnimator scaleAnimatorX = ObjectAnimator.ofFloat(llFirst, "scaleX", 1.0f, 0.8f);
    scaleAnimatorX.setDuration(350);
    ObjectAnimator scaleAnimatorY = ObjectAnimator.ofFloat(llFirst, "scaleY", 1.0f, 0.8f);
    scaleAnimatorY.setDuration(350);
    ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(llFirst, "alpha", 1.0f, 0.5f);
    alphaAnimator.setDuration(350);
    ObjectAnimator rotationAnimatorX = ObjectAnimator.ofFloat(llFirst, "rotationX", 0f, 10f);
    rotationAnimatorX.setDuration(200);
    ObjectAnimator rotationAnimatorY = ObjectAnimator.ofFloat(llFirst, "rotationX", 10f, 0f);
    rotationAnimatorY.setDuration(150);
    rotationAnimatorY.setStartDelay(200);
    ObjectAnimator translationAnimatorX = ObjectAnimator.ofFloat(llFirst, "translationY", 0, -0.1f * firstViewHeight);
    translationAnimatorX.setDuration(350);
    ObjectAnimator translationAnimatorY = ObjectAnimator.ofFloat(llSecond, "translationY", secondViewHeight, 0);
    translationAnimatorY.setDuration(350);
    //监听动画开始
    translationAnimatorY.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationStart(Animator animation) {
            super.onAnimationStart(animation);
            llSecond.setVisibility(View.VISIBLE);
        }
    });
    //把以上动画效果组合起来
    AnimatorSet animatorSet = new AnimatorSet();
    animatorSet.playTogether(scaleAnimatorX, scaleAnimatorY,
            alphaAnimator,
            translationAnimatorX, translationAnimatorY,
            rotationAnimatorX, rotationAnimatorY);
    //开始动画过程
    animatorSet.start();
}

第一个参数表示:此动画的载体,第二个参数表示:要通过什么属性来表现效果

接下来用Button的width属性来讲解方案二和三。view中的layout_width形容的是本view和父容器的关系,比如button和包含它的LinearLayout;而view中的width是用来描述自己本身的,而view的尺寸是由其父控件来决定的,对应父布局的layout_width和layout_height。所以我们对width做属性动画是没有效果的。

方案二:用一个类来包装原始对象,间接为其提供get和set方法
static class ViewWrapper {
    private Button btnTarget;

    public ViewWrapper(Button view) {
        this.btnTarget = view;
    }

  //在set方法中修改Button的width
    public void setWidth(int width) {
        btnTarget.getLayoutParams().width = width;
        btnTarget.requestLayout();
    }

  //如果没有初始值的话还需提供get方法,不然程序直接崩溃
    public int getWidth() {
        return btnTarget.getLayoutParams().width;
    }
}

包装类已经有了,那我们就来实现Button的width动画,Button在3秒的时间内由最初的宽变为原来的2倍。

ViewWrapper viewWrapper = new ViewWrapper(btnWidthAnimation);
ObjectAnimator widthAnimator = ObjectAnimator.ofInt(viewWrapper, "width",
        btnWidthAnimation.getWidth(), 2 * btnWidthAnimation.getWidth());
widthAnimator.setDuration(3000);
widthAnimator.start()
方案三:采用ValueAnimator,监听动画过程,自己实现属性的改变
private void widthAnimation(final View target, final int start, final int end, int duration) {
    ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            IntEvaluator intEvaluator = new IntEvaluator();
            //获取当前帧值
            int currentValue = (int) animation.getAnimatedValue();

            //Elapsed/interpolated fraction of the animation.
            float fraction = animation.getAnimatedFraction();

            target.getLayoutParams().width = intEvaluator.evaluate(fraction, start, end);
            target.requestLayout();
        }
    });
    valueAnimator.setDuration(duration).start();
}

比较方案二和三可以看出,用一个类来包装原始对象,间接为其提供get和set方法较为简单点。

源码:https://github.com/GitPhoenix/NumberAnimation

相关文章

  • 属性动画学习使用总结

    Android 属性动画总结 属性动画的优点 属性动画的使用步骤 实例化属性动画对象 设置属性动画的时长 启动属性...

  • [Android动画]属性动画-小球下落动画实现

    属性动画 属性动画是通过直接改变View属性,实现的动画效果。与补间动画不同的是,属性动画是对象的属性的真实改变,...

  • Android动画-属性动画

    属性动画 所谓属性动画,就是改变对象Object的属性来实现动画过程。属性动画是对View的动画的扩展,通过它可以...

  • 动画之属性动画基础篇

    属性动画 属性动画,改变view或者object的属性实现动画,属性动画比补间动画更强大,不但可以实现旋转、平移等...

  • UI(四十八)属性动画

    属性动画->通过改变图层或者视图上面的属性值(支持动画的属性)产生的动画 属性动画的常用方法属性: 1、初始化 +...

  • iOS - 属性动画

    属性动画->通过改变图层或者视图上面的属性值(支持动画的属性)产生的动画 属性动画的常用方法属性: 1、初始化+(...

  • Android 动画

    动画类型 视图动画(补间动画、逐帧动画)属性动画 补间动画 逐帧动画 属性动画 对比 插值器:确定属性值从初始值过...

  • Android Animation 动画介绍与详解

    一、Animation 动画属性 动画相关的属性:SET属性 二、Animation 动画类型 Android的a...

  • 如何在网页中做出炫酷的动画(使用Spine)

    属性动画和帧动画 web中的动画主要分为属性动画和帧动画两种,属性动画是通过改变dom元素的属性如宽高、字体大小或...

  • 属性动画案例二(加载动画)

    继续属性动画,之前写过 属性动画案例一(基础动画与飘心动画) 简单了解了属性动画,这次来点炫酷的~加载动画,先看一...

网友评论

      本文标题:属性动画

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