Android View动画初步应用

View的动画的分类

  1. 补间动画BetweenAnimation,也就是我们以前一般的Animation。
  2. 帧动画FrameAnimation,通过animation-list实现。
  3. 属性动画PropertyAnimation,从3.0及以后出现的(如果要兼容低版本,可以使用一个民间版第三方的一个jar NineOldAndroid.jar,用法跟系统的用法差不多)。不断地控制控件的属性变化达到动画的效果,一般我们是一些组合的属性动画达到复杂的效果。
属性动画的优势

相对于前面的动画,属性动画更加丰富、好用;属性动画是真实地改变控件的属性,一般的view动画是个假象,平移以后的原来位置还是可以点击的(平移之后的位置不可点击)。

补间动画示例
  • 补间动画支持四种类型:平移(Translate)、旋转(Rotate)、缩放(Scale)、不透明度(Alpha)。
  • 只是显示的位置变动,View的实际位置未改变,表现为View移动到其他地方,点击事件仍在原处才能响应。
  • 组合使用步骤较复杂。
  • View Animation 也是指此动画。

一般来说动画都可以在xml中定义,也可以用纯Java实现,但是一般前者用得比较多。

下面以平移动画为例介绍补间动画。

首先在res下创建anim文件夹,创建动画的xml:

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
           android:duration="500"
           android:fillAfter="true"
           android:fromXDelta="0"
           android:fromYDelta="0"
           android:toXDelta="50%p"
           android:toYDelta="50%p">
</translate>

然后就可以在代码中使用了:

Animation animation = AnimationUtils.loadAnimation(this, R.anim.translate);
iv_icon.startAnimation(animation);

帧动画示例

帧动画一般来说是实现一些复杂的动画,通过图片的变化实现。

  • 用于生成连续的Gif效果图。
  • DrawableAnimation也是指此动画。

首先创建drawable:

<?xml version="1.0" encoding="utf-8"?>
<animation-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="true">
    <item
        android:drawable="@drawable/bga_refresh_mt_refreshing_01"
        android:duration="200"/>
    <item
        android:drawable="@drawable/bga_refresh_mt_refreshing_02"
        android:duration="200"/>
    <item
        android:drawable="@drawable/bga_refresh_mt_refreshing_03"
        android:duration="200"/>
    <item
        android:drawable="@drawable/bga_refresh_mt_refreshing_04"
        android:duration="200"/>
    <item
        android:drawable="@drawable/bga_refresh_mt_refreshing_05"
        android:duration="200"/>
    <item
        android:drawable="@drawable/bga_refresh_mt_refreshing_06"
        android:duration="200"/>
    <item
        android:drawable="@drawable/bga_refresh_mt_refreshing_07"
        android:duration="200"/>
    <item
        android:drawable="@drawable/bga_refresh_mt_refreshing_08"
        android:duration="200"/>

</animation-list>

然后在代码中使用(注意:AnimationDrawable播放动画是依附在window上面的,而在Activity onCreate方法中调用时Window还未初始化完毕,所有才会停留在第一帧,要想实现播放必须在onWindowFocusChanged中播放):

iv_icon.setImageResource(R.drawable.frame_anim);
AnimationDrawable drawable = (AnimationDrawable) iv_icon.getDrawable();
drawable.start();

通过AnimationDrawable可以自由地操作动画,这里就不再赘述了。

属性动画详解
  • 支持对所有View能更新的属性的动画(需要属性的setXxx()和getXxx())。
  • 更改的是View实际的属性,所以不会影响其在动画执行后所在位置的正常使用。
  • Android3.0 (API11)及以后出现的功能,3.0之前的版本可使用github第三方开源库nineoldandroids.jar进行支持。

原理:就是一段时间内通过不断改变View的属性,从而形成动画。

常用API

ObjectAnimator :对象动画执行类。

  • PropertyValuesHolder : 属性存储器,为两个执行类提供更新多个属性的功能。
  • AnimatorListener :动画执行监听,在动画开始、重复、结束、取消时进行回调。
  • Keyframe :为 PropertyValuesHolder提供多个关键帧的操作值。
  • AnimatorSet :一组动画的执行集合类:设置执行的先后顺序,时间等。
  • TimeInterpolator :时间插值,用于控制动画执行过程。
  • ValueAnimator :值动画执行类,常配合AnimatorUpdateListener使用。
  • AnimatorUpdateListener :动画更新监听。
  • TypeEvaluator :类型估值,用于设置复杂的动画操作属性的值。
插值器

常用的插值器有:


1.png

坐标图如下:


1.png
基本的属性动画

View的属性如果过setXXX的话,就可以实现属性动画。通过ObjectAnimator的ofArgb、ofFloat、ofMultiFloat、MultiInt可以实现颜色、不同精度的动画。

下面是一些常见的属性动画:

//平移
ObjectAnimator oa = ObjectAnimator.ofFloat(iv_icon, "translationX", 0f, 300f);
//设置插值器
oa.setInterpolator(new BounceInterpolator());
oa.setDuration(500);
oa.start();

//旋转
ObjectAnimator oa = ObjectAnimator.ofFloat(iv_icon, "rotationX", 0f, 360f);
oa.setDuration(500);
oa.start();

//缩放
ObjectAnimator oa = ObjectAnimator.ofFloat(iv_icon, "ScaleX", 1f, 0.5f);
oa.setDuration(500);
oa.start();

//渐变
ObjectAnimator oa = ObjectAnimator.ofFloat(iv_icon, "Alpha", 1f, 0.5f);
oa.setDuration(500);
oa.start();

组合属性动画

方法一、设置监听

ObjectAnimator animator = ObjectAnimator.ofFloat(iv_icon, "none", 0f, 100f);
animator.setDuration(300);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        //动画在执行的过程当中,不断地调用此方法
        animation.getAnimatedFraction()//百分比
        //得到duration时间内 values当中的某一个中间值。0f~100f
        float value = (float) animation.getAnimatedValue();//
        iv_icon.setScaleX(0.5f + value / 200);//0.5~1
        iv_icon.setScaleY(0.5f + value / 200);//0.5~1
    }
});

//当然也可以监听动画的执行
animator.addListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(Animator animation) {

    }

    @Override
    public void onAnimationEnd(Animator animation) {

    }

    @Override
    public void onAnimationCancel(Animator animation) {

    }

    @Override
    public void onAnimationRepeat(Animator animation) {

    }
});

方法二、使用ValueAnimator

实质同方法一。

ValueAnimator animator = ValueAnimator.ofFloat(0f, 200f);
animator.setDuration(200);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        //动画在执行的过程当中,不断地调用此方法
        animation.getAnimatedFraction();//百分比
        //得到duration时间内 values当中的某一个中间值。0f~100f
        float value = (float) animation.getAnimatedValue();//
        iv_icon.setScaleX(0.5f + value / 200);//0.5~1
        iv_icon.setScaleY(0.5f + value / 200);//0.5~1
    }
});
animator.start();

方法三、使用PropertyValuesHolder

//float... values:代表关键帧的值
PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("alpha", 1f,0.7f,1f);
PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("scaleX", 1f,0.7f,1f);
PropertyValuesHolder holder3 = PropertyValuesHolder.ofFloat("scaleY", 1f,0.7f,1f);

ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(iv_icon, holder1,holder2,holder3);
animator.setDuration(1000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float animatedValue = (float) animation.getAnimatedValue();
        float animatedFraction = animation.getAnimatedFraction();
        long playTime = animation.getCurrentPlayTime();

        System.out.println("animatedValue:"+animatedValue+",  playTime:"+playTime);
    }
});
animator.start();

方法四、使用AnimatorSet

AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(500);
animatorSet.play(animator1);//执行单个动画
animatorSet.playTogether(animator1,animator2,animator3);//同时执行
animatorSet.playSequentially(animator1,animator2,animator3);//依次执行动画

//真正开始执行
animatorSet.start();

综合案例,实现水平抛出
/**
 * x:匀速
 * y:加速度   y=1/2*g*t*t
 * 使用估值器最好实现。
 */
ValueAnimator valueAnimator = new ValueAnimator();
valueAnimator.setDuration(4000);
//        valueAnimator.setFloatValues(values)
valueAnimator.setObjectValues(new PointF(0, 0));
//估值器---定义计算规则
valueAnimator.setEvaluator(new TypeEvaluator<PointF>() {
    @Override
    public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
        //拿到每一个时间点的坐标
        //x=v*t (s秒)
        PointF pointF = new PointF();
        float time = fraction * 10;
        pointF.x = 100f * time;//初始速度*(执行的百分比*4,即时间t)
        pointF.y = 0.5f * 9.8f * time * time;
        return pointF;
    }
});

valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        //得到此时间点的坐标
        PointF pointF = (PointF) animation.getAnimatedValue();
        iv_icon.setX(pointF.x);
        iv_icon.setY(pointF.y);
    }
});
valueAnimator.start();


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值