动画

简介

Android中的动画大致分为三类:view动画、帧动画、属性动画。

view动画

又叫补间动画。支持四种动画操作,分别是平移动画、旋转动画、缩放动画、透明度动画,当让也可以设置动画集,里面添加任意个四种动画操作。

原理:通过父容器来绘制自己动画时的样子;实际上自己本身没有进行动画,自身还在原先的位置上没有改变。

作用对象:View
使用

  • 通过XML文件定义
  • 在res目录中创建anim文件,在该文件中创建XML文件
  • 使用的标签是<set>
<?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" />

	<translate
		android:fromXDelta="500"
		android:toXDelta="0" />
</set>
在代码中使用

Button button = (Button) findViewById(R.id.hello);
Animation animation = AnimationUtils.loadAnimation(this,R.anim.myanimation);
button.startAnimation(animation);
在代码中创建

Button button = (Button) findViewById(R.id.hello);
AlphaAnimation animation = new AlphaAnimation(0, 1);
animation.setDuration(300);
button.startAnimation(animation);

分类

  • AlphaAnimation:渐变动画,从无到有
  • RotateAnimation:旋转动画
  • ScaleAnimation:比例动画,从小到大
  • TranslateAnimation:位移动画
  • AnimationSet:动画集合(包含多个动画)

特殊应用:使用LayoutAnimation作用于ViewGroup,为其制定一个动画,这样他所有的子元素具有这种动画效果

1、定义动画(指定子元素的入场动画)
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:shareInterpolator="true">

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

    <translate android:fromXDelta="500"
               android:toXDelta="0"/>
</set>
2、定义layoutAnimation

<?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>
3、设置ViewGroup的属性
<ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layoutAnimation="@anim/anim_layout"
        android:background="#fff4f7f9"
        android:cacheColorHint="#00000000"
        android:divider="#dddbdb"
        android:dividerHeight="1.0dp"
        android:listSelector="@android:color/transparent">

</ListView>
也可以在代码中实现(通过使用LayoutAnimationController实现)
ListView listView = (ListView) findViewById(R.id.list);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_item);
LayoutAnimationController controller = new LayoutAnimationController(animation);
controller.setDelay(0.5f);
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
listView.setLayoutAnimation(controller);

Activity的切换效果(使用overridePendingTransition(int enterAnim, int exitAnim))

  • enterAnim:Activity 被打开时所需要的动画资源id
  • exitAnim:Activity 被关闭时所需要的动画资源id
  • overridePendingTransition()方法必须在startActivity或者finish之后,否则没有效果
Intent intent = new Intent(MainActivity.this, Demo01.class);
startActivity(intent);
overridePendingTransition(R.anim.anim_enter, R.anim.anim_exit);

@Override
public void finish() {
    super.finish();
    overridePendingTransition(R.anim.anim_enter, R.anim.anim_exit);
}
Fragment添加动画

通过FragmentTransaction中的setCustomAnimation()方法设置切换效果

属性动画

Property Animation。在一个时间间隔内完成对象从一个属性值到另一个属性值的改变
原理:通过改变自身的属性来显示动画;自身真正的动了起来。
分类
  • ObjectAnimator
  • ValueAnimator
  • AnimatorSet
使用代码创建
public void translate(View view){
    //arg0:要操作的对象;arg1:要修改的属性的名字
    ObjectAnimator  oa1 = ObjectAnimator.ofFloat(imageView, "translationX", 0, 30,70,120);
    //定义动画持续时间
    oa1.setDuration(2000);
    //设置重复播放次数
    oa1.setRepeatCount(2);
    //设置重复模式
    oa1.setRepeatMode(ValueAnimator.REVERSE);
    //播放动画
    oa1.start();
}
动画集
AnimatorSet set = new AnimatorSet();
set.playTogether(
        ObjectAnimator.ofFloat(view, "rotationX", 0, 360),
        ObjectAnimator.ofFloat(view, "rotationY", 0, 180),
        ObjectAnimator.ofFloat(view, "rotation", 0, -90),
        ObjectAnimator.ofFloat(view, "translationX", 0, 90),
        ObjectAnimator.ofFloat(view, "translationY", 0, 90),
        ObjectAnimator.ofFloat(view, "scaleX", 0, 1.5f),
        ObjectAnimator.ofFloat(view, "scaleY", 0, 0.5f),
        ObjectAnimator.ofFloat(view, "alpha", 1, 0.25f,1)
);
set.setDuration(5*1000).start();
属性动画中两个重要概念:


* 插值器——根据时间流逝的百分比计算出当前属性值改变的百分比

* LinearInterpolator(线性插值器:匀速动画)

* AccelerateDecelerateInterpolator(加速减速插值器:动画两头慢中间快)

* DecelerateInterpolator(减速插值器:动画越来越慢)


* 估值器——根据当前属性改变的百分比计算出改变后的属性

* IntEvaluator(针对整型属性)

* FloatEvaluator(针对浮点型属性)

* ArgbEvaluator(针对Color属性)


* 自定义插值器需要实现Interpolator或者TimeInterpolator,自定义估值算法需要实现TypeEvaluator

属性动画的监听器:

  • AnimationListener
  • AnimatorListenerAdapter:AnimationListener的适配器,可以选择性的实现自己需要的方法
  • AnimatorUpdateListener:监听动画的整个过程,动画每播放一帧就会调用一次(默认每20ms一帧)
对任意属性做动画:
属性动画要求动画作用的对象提供该属性的get和set方法:
  • 对象必须提供set**方法,如果动画的时候没有传递初始值,那么还需要提供get**方法,因为系统要去获取对象的**属性初始值(该条不满足程序直接crash)
  • 对象的set**对属性**所做的改变必须能够通过某种方法反映出来,比如会带来UI的改变之类(该条不满足,动画无效果但不会crash)
解决上述问题的方法:
  • 如果有权限的话,给对象加上get和set方法
  • 用一个类包装原始对象,间接为其提供get和set方法
//调用performAnimate()方法即可实现mView对象在5秒内宽度变为500
private void  performAnimate(){
    ViewWrapper wrapper = new ViewWrapper(mView);
    ObjectAnimator.ofInt(wrapper,"width",500).setDuration(5000).start();
}
//自定义的类封装原始对象并提供了该对象的宽度的set和get方法
private static class ViewWrapper{
    private View mTarget;

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

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

    public void setWidth(int width) {
        mTarget.getLayoutParams().width = width;
        mTarget.requestLayout();
    }
}
采用ValueAnimator,监听动画过程,自己实现属性的改变
//调用该方法可以实现对象在5秒内宽度变为500
private void performAnimate(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) {
            //获取当前动画的进度值(1-100之间)
            int currentValue = (int) animation.getAnimatedValue();
            //获取当前进度占整个动画过程的比例(0-1之间)
            float fraction = animation.getAnimatedFraction();
            //直接调用整型估值器,通过比例计算出宽度,再将该值设置给被操作的 View
            target.getLayoutParams().width = mEvaluator.evaluate(fraction, start, end);
            target.requestLayout();
        }
    });
    valueAnimator.setDuration(5000).start();
}

帧动画

Drawable Animation,多张图片快速切换,形成动画效果
<?xml version="1.0" encoding="utf-8"?>
<animation-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item
        android:drawable="@drawable/pic1"
        android:duration="500"/>
    <item
        android:drawable="@drawable/pic2"
        android:duration="500"/>
    <item
        android:drawable="@drawable/pic3"
        android:duration="500"/>
    <item
        android:drawable="@drawable/pic4"
        android:duration="500"/>
</animation-list>
使用
Button button = (Button) findViewById(R.id.jumpto1);
button.setBackgroundResource(R.drawable.myanimation);
AnimationDrawable drawable = (AnimationDrawable) button.getBackground();
drawable.start();

使用动画注意事项:

  • OOM,尤其是侦动画中图片数量以及图片过大
  • 内存泄漏,属性动画中出现无限循环并且在Activity退出的时候没有及时停止
  • 补间动画是对View影像做动画,有可能出现动画完成之后View无法隐藏,需要使用view.clearAnimation()进行清除。
  • 兼容性问题
  • 不要使用px,尽量使用dp
  • 动画元素的交互
  • 硬件加速

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值