mthoutai

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

随着我对自己定义view了解的深入。呆板的效果已经无法满足须要,那么为了更好的效果,动画当然是最佳的选择,Android 动画能够分为三种:view动画,帧动画,属性动画.尽管前两种使用比較简单但View animation。仅仅能支持简单的缩放、平移、旋转、透明度主要的动画,而且仅仅是改变了View对象绘制的位置,没有改变View对象本身。仅仅适合不须要交互的界面,而帧动画是顺序的播放一组预先定义好的图片局限性很大,而属性动画直接改动了view对象的属性,攻克了前两个动画的不足,所曾经两种动画本文略了重点就是介绍3.0以后android推出的属性动画

1.概述

属性动画顾名思义,在动画的同一时候更改对象的属性,而且不止能够应用于View,能够对随意对象的属性进行动画,表示一个值在一段时间内的改变,当值改变时要做什么事情全然是你自己决定的。动画默认的持续时间300ms,默认帧率10ms/帧.

比較经常使用的类:

ObjectAnimator,ValueAnimator,AnimatorSet当中ObjectAnimator是ValueAnimator的子类,平时最经常使用的也是ObjectAnimator,AnimatorSet是动画集合,具体使用方法后面会具体解说

比較经常使用的属性:

Duration:动画持续时间

TimeInterpolator:时间插值器,它的作用是依据时间流逝的百分比计算出插值。这样说比較抽象,比方系统提供的LinearInterpolator线性插值器讲到这个大家应该知道插值器是干嘛的了。

TypeEvaluator:估值器。依据前面TimeInterpolator算出的值结合開始值,结束值计算出当前时间的属性值。

Frame refresh delay:帧刷新延迟。对于你的动画。多久刷新一次帧;默觉得10ms,但终于依赖系统的当前状态;基本不用管。

Repeat Count and behavoir:反复次数与方式。如播放3次、5次、无限循环。能够此动画一直反复,或播放完时再反向播放

整个属性值计算流程就是:依据动画已进行的时间跟动画总时间(duration)的比计算出一个时间因子(0~1),然后TimeInterpolator依据时间因子(0~1)计算出还有一个因子,最后TypeAnimator通过这个因子计算出当前时间属性值。

2.ObjectAnimator

先来看一个很easy的样例用ObjectAnimator实现X轴方向平移

activity代码

package com.byzk.www.animatordemo;

import android.animation.ObjectAnimator;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button bt = (Button) findViewById(R.id.bt);
        final TextView tv = (TextView) findViewById(R.id.tv);
        bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tv,"translationX",300);
                objectAnimator.setDuration(2000).start();


            }
        });
    }

}

ObjectAnimator.ofFloat()这种方法是依据要改动属性的类型来定。由于这里translation数值为float型所以这里使用ofFloat()

布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:background="#f00" />

    <Button
        android:id="@+id/bt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="点我" />

</LinearLayout>

效果

这里写图片描写叙述

是不是很easy的实现了滑动,通过ObjectAnimator的静态工厂方法创建一个ObjectAnimator对象第一个參数是要操作的view,第二个參数是要改动的属性,第三个參数是可变数组參数,假设仅仅设置一个參数的话,那么该属性必须有get方法,由于它表示当前值变化到设置值,而内部是通过反射机制来调用来改动相应属性值。

这里有点须要注意,操作的属性必须有get,set方法(这里系统已经实现了translationX的set,get方法)。不然动画无法起效。只是即使没有也没关系。有三种方法能够实现相应的效果:

1.加入set,get方法

2.写一个包装类并加入set,get方法去改动相应属性值

3.用ValueAnimator实现

很显然第一种方式我们没法实现由于我们没法改动sdk中代码所以主要方法就是2。3这里先给出另外一种方式的代码,第三种方式ValueAnimator中解说。

用包装类实现没有set,get方法属性动画

package com.byzk.www.animatordemo;

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button bt = (Button) findViewById(R.id.bt);
        final TextView tv = (TextView) findViewById(R.id.tv);
        bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                ObjectAnimator objectAnimator = ObjectAnimator.ofInt(new MyTextView(tv),"width",0,300);
                objectAnimator.setDuration(2000);
                objectAnimator.start();

            }
        });
    }
    public class MyTextView{
        private final TextView tv;

        public MyTextView(TextView tv) {
            this.tv = tv;
        }

        public void setWidth(int width){
            tv.getLayoutParams().width = width;
            tv.requestLayout();
        }

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

    }
}

3.ValueAnimator

valueAnimator本身没有动画效果,主要通过起始值。结束值,插值器,估值器计算当前时间属性值。回调AnimatorUpdateListener接口中onAnimationUpdate方法,将当前时间属性值回调然后在设置给相应属性完毕动画。

ValueAnimator实现没有get,set方法属性动画

package com.byzk.www.animatordemo;

import android.animation.ValueAnimator;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button bt = (Button) findViewById(R.id.bt);
        final TextView tv = (TextView) findViewById(R.id.tv);
        bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 300);
                valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        int animatedValue = (int) animation.getAnimatedValue();//回调属性值
                        tv.getLayoutParams().width = animatedValue;
                        tv.requestLayout();
                    }
                });
                valueAnimator.setDuration(1000).start();

            }
        });
    }
}

4.AnimatorSet和PropertyValuesHolder

两个类都能够实现相似于AnimationSet的动画集的效果.

PropertyValuesHolder:

PropertyValuesHolder holder = PropertyValuesHolder.ofFloat("translationX", 300);
PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("scaleX", 0.5f);
PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("scaleY", 2f);
ValueAnimator valueAnimator = ObjectAnimator.ofPropertyValuesHolder(tv,holder, holder1, holder2);
valueAnimator.setDuration(2000).start();

AnimatorSet:

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tv, "translationX", 300);
ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(tv, "scaleX", 0.5f);
ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(tv, "scaleY", 2f);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(objectAnimator,objectAnimator1,objectAnimator2);
animatorSet.setDuration(2000).start();

AnimatorSet更加强大能够更加精准的控制动画的运行顺序。

AnimatorSet as= new AnimatorSet();
as.play(anim1).before(anim2); 
as.play(anim2).with(anim3); 
as.play(anim2).with(anim4) 
as.play(anim5).after(amin2); 
as.start();

5.xml中使用属性动画

跟视图动画一样属性动画也能够写在xml中

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:propertyName="translationX"
    android:valueTo="300"
    android:valueType="floatType"

    />

通过AnimatorInflater去载入xml中属性动画

Animator animator = AnimatorInflater.loadAnimator(MainActivity.this,R.animator.animator_tv);
                animator.setTarget(tv);
                animator.start();

6.动画监听

objectAnimator.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) {

                    }
                });

除了上面这样的实现全部方法的,android还给我们提供了一个AnimatorListenerAdapter。即AnimatorListener接口的空实现。须要什么的时候就重写什么方法完毕监听

7.TimeInterpolator和TypeEvaluator

普通情况下插值器和估值器使用系统自带的就可以完毕大部分任务,假设实在须要自己定义炫酷的效果能够又一次实现插值器和估值器

objectAnimator.setInterpolator(new TimeInterpolator() {
                    @Override
                    public float getInterpolation(float input) {
                        return 0;//插值器的实现
                    }
                });
objectAnimator.setEvaluator(new TypeEvaluator() {
                    @Override
                    public Object evaluate(float fraction, Object startValue, Object endValue) {
                        return null;//估值器的实现
                    }
                });

8.View的anim方法

为了方便使用动画还能够view.animate()这样写来

iv.animate().alpha(0.5f)
                .setDuration(2000)
                .setListener(new AnimatorListenerAdapter() {

                })
                .start();

到这里属性动画的基本使用就解说完了以后还会写一些利用属性动画实现好看效果的自己定义控件。

posted on 2017-06-29 11:21  mthoutai  阅读(259)  评论(0编辑  收藏  举报