视图动画与属性动画基础

安卓坐标系:

Android 系统的坐标系,屏幕左上角为坐标原点,假如屏幕为1080*1980,那么左上角为(0,0),右上角为(1080,0),左下角为(0,1980),右下角为(1080,1980)

一:变换动画(Tween Animation)

此动画也被称作补间动画,视图动画。可以在一个视图容器内执行一系列简单变换(位置、大小、旋转、透明度)。如果有一个ImageView对象,可以实现移动、旋转、缩放、透明度设置其文本。

Tween Animation只能应用于View对象,而且只支持一部分属性,如支持缩放旋转而不支持背景颜色的改变。

而且对于View animation,它只是改变了View对象绘制的位置,而没有改变View对象本身

可以给一个View同时设置多个动画,比如从透明至不透明的淡入效果,与从小到大的放大效果,这些动画可以同时进行,也可以在一个完成之后开始另一个。

公共属性: 

属性描述
Duration动画持续时间(毫秒)
fillAfter设置为true,动画转化在动画结束后被应用
fillBefore设置为true,动画转化在动画开始前被应用
interpolator动画插入器(加速,减速)
repeatCount动画重复次数
repateMode顺序/倒序重复
startOffset动画之间的时间间隔

 

javaxml描述
AlphaAnimation<alpha> 放置在res/anim/目录下渐变透明度动画效果
RotateAnimation<rotate> 放置在res/anim/目录下画面转移旋转动画效果
ScaleAnimation<scale> 放置在res/anim/目录下渐变尺寸伸缩动画效果
TranslateAnimation<translate> 放置在res/anim/目录下画面转换位置移动动画效果
AnimationSet<set> 放置在res/anim/目录下

一个持有其它动画元素alpha、scale、translate、rotate或者其它set元素的容器

(java代码实现比xml实现更灵活)

1.Alpha:渐变透明度动画

实现方法:xml布局形式:指定一个布局文件:res->anim->alpha

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

    <alpha
        android:duration="1000"
        android:fromAlpha="0.1"
        android:toAlpha="1.0">
    </alpha>
<!--
duration:指定动画持续时间
fromAlpha,toAlpha:分别指定动画起始和结束的透明度
-->
</set>

然后在java代码中调用工具类,并实现给view对象添加动画:

case R.id.btn_Alpha:
//                利用AnimationUtils工具类,指定alphaXML文件,添加一个动画
                loadAnimation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.alpha);
//                为imageView添加动画
                imageView.startAnimation(loadAnimation);
                break;

 

2.Scale:渐变尺寸缩放动画

实现方法与Alpha类似,不再累赘:

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

    <scale
        android:duration = "1000"
        android:fillAfter = "false"
        android:fromXScale="0.0"
        android:fromYScale="0.0"
        android:interpolator = "@android:anim/accelerate_decelerate_interpolator"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="1.0"
        android:toYScale="1.0">
    </scale>

    <!--
    pivotX,pivotY:指定view的中心点进行缩放
    -->

</set>
case R.id.btn_Scale:
                loadAnimation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.scale);
                imageView.startAnimation(loadAnimation);
                break;

3.Translate:位置移动动画

实现方法与Alpha类似,不再累赘:

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

    <translate
        android:duration = "1000"
        android:fromXDelta="10"
        android:fromYDelta="10"
        android:toXDelta="100"
        android:toYDelta="100">
    </translate>

</set>
 case R.id.btn_Translate:
                loadAnimation = AnimationUtils.loadAnimation(MainActivity.this,R.anim.translate);
                imageView.startAnimation(loadAnimation);
                break;

4.Rotate:旋转动画

实现方法与Alpha类似,不再累赘:

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

    <rotate
        android:duration = "2000"
        android:fromDegrees="0"
        android:interpolator = "@android:anim/accelerate_decelerate_interpolator"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="360">
    </rotate>

</set>
case R.id.btn_Rotate:
                loadAnimation = AnimationUtils.loadAnimation(MainActivity.this,R.anim.rotate);
                imageView.startAnimation(loadAnimation);
                  break;

5.组合动画

case R.id.btn_zuhe:
/*
* 方法1:通过为当前loadAnimation实现监听器,重写方法后,在onAnimationEnd(Animation animation)方法中执行定义的第二个动画
* */
                loadAnimation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.alpha);
                imageView.startAnimation(loadAnimation);
                final  Animation loadAnimation2 = AnimationUtils.loadAnimation(MainActivity.this, R.anim.rotate);
                loadAnimation.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {
                        
                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        imageView.startAnimation(loadAnimation2);
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {

                    }
case R.id.btn_zuhe2:
                /*
                * 方法二:设定一个动画集:
                * 写一个动画集,AnimationSet,在其中定义动画A和B,为动画B设置startOffset,其值就是前一个动画播放所需的时间
                * */
                loadAnimation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.continue_btn2);
                imageView.startAnimation(loadAnimation);
                break;

6:Activity切换动画

case R.id.btn_change:
                /*
                * 此实例显示Activity之间跳转时的动画
                * overridePendingTransition()方法,第一个参数传入进入新活动的动画,第二个参数传递推出此活动时的动画
                * */
                Intent intent = new Intent(MainActivity.this, Main2Activity.class);
                startActivity(intent);
                overridePendingTransition(R.anim.rotate, R.anim.alpha);
                break;

二:帧动画(Frame Animation)

逐帧动画:

使用animation-list标签来分组一个item标签集合,定义要显示的图片,指定显示它的时间(毫秒)

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

    <item
        android:drawable="@drawable/one"
        android:duration="500"/>
    <item
        android:drawable="@drawable/two"
        android:duration="500"/>
    <item
        android:drawable="@drawable/three"
        android:duration="500"/>
    <item
        android:drawable="@drawable/four"
        android:duration="500"/>
    <item
        android:drawable="@drawable/five"
        android:duration="500"/>
    <item
        android:drawable="@drawable/six"
        android:duration="500"/>

</animation-list>

在java代码中调用:

case R.id.btn_Frame:
//                设置动画XML资源
                imageView.setImageResource(R.drawable.anim_list);
//                获取动画对象
                AnimationDrawable animationDrawable = (AnimationDrawable) imageView.getDrawable();
//                启动动画
//                停止动画可用.stop()方法
                animationDrawable.start();
                break;

 

三:布局动画(Layout Animation)

 所谓的布局动画是指作用的ViewGroup上,给ViewGroup增加子View时添加一个动画过度效果。使用LayoutAnimationController。

下面是加载一个具有ListView的Activity,显示相应的动画效果

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);

        initView();
        list = new ArrayList<String>();
        addListitem();
//        ArrayAdapter<>第一个参数传入上下文对象,第二个参数传入listview子项布局,第三项传入list对象(资源)
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.listitem, list);
        listView.setAdapter(adapter);
//        通过layoutAnimationController添加动画
        LayoutAnimationController layoutAnimationController = new LayoutAnimationController(AnimationUtils.loadAnimation(Main3Activity.this, R.anim.list_in));
//        指定子项动画加载的顺序
        layoutAnimationController.setOrder(LayoutAnimationController.ORDER_RANDOM);
        //        将此动画附在listview上
        listView.setLayoutAnimation(layoutAnimationController);
        listView.startLayoutAnimation();
    }

    private void addListitem() {
        for (int i = 0; i < 50; i++){
            list.add("liebiaoxiang:" + i);
        }
    }

    private void initView() {
        listView = findViewById(R.id.listview);
    }

 

 

四:属性动画(Property Animation)

属性动画系统是一个强大的框架,允许动画几乎任何东西。可以定义动画以随时间更改任何对象属性,无论它是否绘制到屏幕上。属性动画在指定的时间长度内更改属性(对象中的字段)值。要为某些内容设置动画,请指定要设置动画的对象属性,例如对象在屏幕上的位置,要为其设置动画的时间长度以及要在其间设置动画的值。

属性动画系统允许定义动画的以下特征:

  • 持续时间:您可以指定动画的持续时间。默认长度为300毫秒。
  • 时间插值:您可以指定如何计算属性值作为动画当前已用时间的函数。
  • 重复计数和行为:您可以指定是否在到达持续时间结束时重复动画以及重复动画的次数。您还可以指定是否要反向播放动画。将其设置为反向向前播放动画然后反复向后播放动画,直到达到重复次数。
  • 动画设置:您可以将动画分组为一起或按顺序或在指定延迟后播放的逻辑集。
  • 帧刷新延迟:您可以指定刷新动画帧的频率。默认设置为每10毫秒刷新一次,但应用程序刷新帧的速度最终取决于系统整体的繁忙程度以及系统为基础计时器提供服务的速度。
描述
ValueAnimator属性动画的主要计时引擎,它还计算要设置动画的属性的值。它具有计算动画值的所有核心功能,包含每个动画的计时详细信息,有关动画是否重复的信息,接收更新事件的侦听器以及设置要评估的自定义类型的功能。动画属性有两个部分:计算动画值并在正在设置动画的对象和属性上设置这些值。ValueAnimator不会执行第二部分,因此您必须侦听由计算的值的更新,ValueAnimator并使用您自己的逻辑修改要设置动画的对象。
ObjectAnimator其子类ValueAnimator允许您将目标对象和对象属性设置为动画。此类在计算动画的新值时会相应地更新属性。您希望在ObjectAnimator大多数情况下使用 它,因为它使得在目标对象上设置动画值的过程变得更加容易。但是,您有时希望ValueAnimator直接使用,因为ObjectAnimator还有一些限制,例如要求在目标对象上存在特定的acessor方法。
AnimatorSet提供一种将动画分组在一起的机制,以便它们相互运行。您可以将动画设置为一起播放,按顺序播放,或在指定的延迟播放后播放。

1.ObjectAnimator

简单的实例演示ObjectAnimator的应用:(用button实现监听事件实现imageview动画效果)

case R.id.btn_move:
//                move1();//简单的ObjectAnimator的使用
//                move2();//用PropertyValuesHolder实现
                move3();//用AnimatorSet实现
                break;

/*
     * propertyName:
     *               若属性具有get()/set(),就可以通过属性动画操作此属性
     *               X/Y
     *               translationX/translationY
     *               rotation
     *               ...
     * */
private void move1() {
//        第一个参数是所要操作的对象,第二个参数是操作的属性,第三个参数地范围变化
        /*
         * 此三个动画会同步执行
         * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
         * */
        ObjectAnimator.ofFloat(imageView, "translationX", 0F, 200F).
                setDuration(1000).
                start();
        ObjectAnimator.ofFloat(imageView, "translationY", 0F, 200F).
                setDuration(1000).
                start();
        ObjectAnimator.ofFloat(imageView, "rotation", 0F, 360F).
                setDuration(1000).
                start();
        /*
         * 此三个动画会同步执行
         * 调用start()方法后,为异步过程,所以三个动画同时起了作用
         * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
         * */
    }
private void move2() {
        /*
        * 此方法利用PropertyValuesHolder实现多动画效果的共同实现
        * 优点:比move1()方法,更有效率,同时节省资源
        * */
        PropertyValuesHolder p1 = PropertyValuesHolder
        .ofFloat("rotation", 0, 360F);
        PropertyValuesHolder p2 = PropertyValuesHolder
                .ofFloat("translationY", 0, 360F);
        PropertyValuesHolder p3 = PropertyValuesHolder
                .ofFloat("translationX", 0, 360F);

        ObjectAnimator.ofPropertyValuesHolder(imageView, p1, p2, p3)
                .setDuration(1000)
                .start();
    }
private void move3() {
        /*
        * 利用动画集AnimatorSet实现多动画效果
        * */
        ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(imageView, "translationX", 0F, 200F);
        ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(imageView, "translationY", 0F, 200F);
        ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(imageView, "rotation", 0F, 360F);
        AnimatorSet animatorSet = new AnimatorSet();
//        用play()方法.with().after()可自定义动画顺序
//        同时执行多种动画效果
//        animatorSet.playTogether(objectAnimator1,objectAnimator2,objectAnimator3);
//        顺序执行多种动画效果
        animatorSet.playSequentially(objectAnimator1,objectAnimator2,objectAnimator3);
        animatorSet
                .setDuration(2000)
                .start();
    }

 

为动画添加监听事件(此实例为button自身添加了动画,并添加了监听事件)

 case R.id.btn_click:
                click(btn_click);
                break;

...

private void click(View view) {
        ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 0F, 1F)
                .setDuration(2000);

//        增加监听事件:方法一     用animator.addListener(new Animator.AnimatorListener()
//        animator.addListener(new Animator.AnimatorListener() {
//            @Override
//            public void onAnimationStart(Animator animation) {
//
//            }
//
//            @Override
//            public void onAnimationEnd(Animator animation) {
//                Toast.makeText(MainActivity.this, "anim end", Toast.LENGTH_SHORT).show();
//            }
//
//            @Override
//            public void onAnimationCancel(Animator animation) {
//
//            }
//
//            @Override
//            public void onAnimationRepeat(Animator animation) {
//
//            }
//        });

//        增加监听事件:方法二       用animator.addListener(new AnimatorListenerAdapter()
//        减少无关的代码
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                Toast.makeText(MainActivity.this, "anim end", Toast.LENGTH_SHORT).show();
            }
        });

        animator.start();
    }

2.ValueAnimator

ValueAnimator包含Property Animation动画的所有核心功能,如动画时间,开始、结束属性值,相应时间属性值计算方法等。应用Property Animation有两个步聚:

  1. 计算属性值
  2. 根据属性值执行相应的动作,如改变对象的某一属性。

ValuAnimiator只完成了第一步工作,如果要完成第二步,需要实现ValueAnimator.onUpdateListener接口,这个接口只有一个函数onAnimationUpdate(),在这个函数中会传入ValueAnimator对象做为参数,通过这个ValueAnimator对象的getAnimatedValue()函数可以得到当前的属性值。

    /*
    *用button中Text数值的增长监测ValueAnimator生成的数值
    */
    public void click(View view){
        final Button button = (Button) view;
        ValueAnimator animator = ValueAnimator.ofInt(0, 100);
        animator.setDuration(10000);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Integer value = (Integer) animation.getAnimatedValue();
                button.setText("" + value);
            }
        });
        animator.start();
    }

    public void click(View view){
//        可以在ValueAnimator.ofObject(new TypeEvaluator()时,给TypeEvaluator指定一个泛型
        ValueAnimator animator = ValueAnimator.ofObject(new TypeEvaluator<PointF>() {
            /*
            * 重写evaluate,返回需要的值
            * 第一个参数:0到1之间变化的时间因子
            * */
            @Override
            public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
                return null;
            }
        });
    }

3.插值器

Interpolator负责控制动画变化的速率,使得基本的动画效果能够以匀速、加速、减速、抛物线速率等各种速率变化。 

画是开发者给定开始和结束的“关键帧”,其变化的“中间帧”是有系统计算决定然后播放出来。因此,动画的每一帧都将在开始和结束之间的特定时间显示。此时动画时间被转换为时间索引,则动画时间轴上的每个点都可以转换成0.0到1.0之间的一个浮点数。然后再将该值用于计算该对象的属性变换。

在变换的情况下,y轴上,0.0对应于起始位置,1.0对应于结束位置,0.5对应于起始和结束之间的中间,对于一些插值器其值还可以是0~1之外的数值。
 

    

 五:属性动画与视图动画的区别

视图动画系统提供仅为View 对象设置动画的功能,因此如果要为非View对象设置动画,则必须实现自己的代码才能执行此操作。视图动画系统也受到约束,因为它仅将View对象的一些方面暴露给动画,例如视图的缩放和旋转而不是背景颜色。

视图动画系统的另一个缺点是它只修改了绘制视图的位置,而不是实际的视图本身。例如,如果您设置了一个按钮以在屏幕上移动,则该按钮会正确绘制,但您可以单击该按钮的实际位置不会更改,因此您必须实现自己的逻辑来处理此问题。

使用属性动画系统,可以完全删除这些约束,并且可以为任何对象(视图和非视图)的任何属性设置动画,并且实际修改了对象本身。属性动画系统在执行动画方面也更加强大。在较高级别,您可以将动画师分配给要设置动画的属性,例如颜色,位置或大小,并可以定义动画的各个方面,例如多个动画师的插值和同步。

但是,视图动画系统设置时间较短,编写代码较少。如果视图动画完成了您需要执行的所有操作,或者现有代码已按您所需的方式工作,则无需使用属性动画系统。如果出现用例,将两种动画系统用于不同情况也是有意义的。

 

   

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值