Android动画

来源:互联网 发布:macbookair软件推荐 编辑:程序博客网 时间:2024/05/17 00:53

一、动画概述


动画作为广泛存在于程序界面中的效果,具有相似的属性,Android中动画通用的属性包括:

1、目标(target):View

2、时长(duration):duration

3、开始状态(from):fromXXX

4、结束状态(to):toXXX

5、开始时间(beginTime):startOffset

6、重复次数(repeatCount):repeatCount

7、时间轴(timeLine):interpolator


Android动画主要分为两类:视图动画和属性动画(API 11)


二、视图动画:


1、TweenAnimation


TweenAnimation具有四种变换效果,其包括四个子类:TranslateAnimation(平移动画)、ScaleAnimation(缩放动画)、

RotateAnimation(旋转动画)、AlphaAnimation(透明度动画)以及组合动画类:AnimationSet

以下是每个变换效果中其他常用属性:

<?xml version="1.0" encoding="utf-8"?><!-- set标签代表动画组合     shareInterpolator 组合中动画是否共享同一插值器     startOffset       组合中动画是否共享同一开始时间--><set xmlns:android="http://schemas.android.com/apk/res/android">    <!-- 其他通用属性:         interpolator 插值器         fillAfter    结束时是否停留在结束位置    -->    <!-- fromAlpha 起始透明度         toAlpha   结束透明度         说明:              0.0表示完全透明              1.0表示完全不透明-->    <alpha        android:interpolator="@android:anim/cycle_interpolator"        android:fillAfter="true"        android:fromAlpha="1.0"        android:toAlpha="0.0">    </alpha>    <!-- fromXScale 起始X坐标的伸缩尺寸         fromYScale 起始Y坐标的伸缩尺寸         toXScale   结束X坐标的伸缩尺寸         toYScale   结束Y坐标的伸缩尺寸         说明:              0.0表示收缩到没有              1.0表示正常无伸缩              值小于1.0表示收缩              值大于1.0表示放大         pivotX    相对于控件X坐标的开始位置         pivotY    相对于控件Y坐标的开始位置         说明:              以上两个属性值 从0%-100%中取值              50%为控件的X或Y方向坐标上的中点位置-->    <scale        android:fromXScale="1"        android:fromYScale="1"        android:toXScale="2"        android:toYScale="2"        android:pivotX="50%"        android:pivotY="50%">    </scale>    <!-- fromXDelta 属性为动画起始时 X坐标上的位置         toXDelta   属性为动画结束时 X坐标上的位置         fromYDelta 属性为动画起始时 Y坐标上的位置         toYDelta   属性为动画结束时 Y坐标上的位置         注意:              100%为控件自身宽或高的一倍                  负值为反方向              100%p为屏幕宽或高的一倍      负值为反方向-->    <translate android:fromXDelta="0"        android:fromYDelta="0"                android:toXDelta="200"                android:toYDelta="200">     </translate>     <!-- fromDegrees 起始时控件角度          toDegrees 结束时控件旋转角度          pivotX 相对于控件的X坐标开始位置          pivotY 相对于控件的Y坐标开始位置-->     <rotate android:fromDegrees="0"             android:toDegrees="360"             android:pivotX="50%"             android:pivotY="50%">     </rotate></set>



应用动画:

<pre name="code" class="java" style="font-size: 13.3333px;">Animation animation = AnimationUtils.loadAnimation(this , R.anim.anim_set);
animation.setRepeatCount(2);//通过代码设置动画,其他属性相同imageView.startAnimation(animation);

动画的组合除可并行外,也可串行,设置串行动画方法有两种:

1、设置startOffset,使不同动画时间相错

2、设置监听器

animation.setAnimationListener(new Animation.AnimationListener() {            @Override            public void onAnimationStart(Animation animation) {                            }            @Override            public void onAnimationEnd(Animation animation) {            }            @Override            public void onAnimationRepeat(Animation animation) {            }        });



2、Frame动画:


Frame动画即帧动画,其原理就如同电影一般,一帧一帧播放形成动画的效果


首先在XML中定义AnimationDrawable

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"    android:oneshot="false" >    <item android:drawable="@drawable/progress_one" android:duration="200"></item>    <item android:drawable="@drawable/progress_two" android:duration="200"></item>    <item android:drawable="@drawable/progress_three" android:duration="200"></item>    <item android:drawable="@drawable/progress_four" android:duration="200"></item></animation-list>


应用Frame动画

imageView.setBackgroundResource(R.drawable.loading);AnimationDrawable drawable = (AnimationDrawable) imageView.getBackground();drawable.start();



3、特殊使用场景:


LayoutAnimation作用于ViewGroup,为其子元素指定一个动画


1、定义LayoutAnimation

<?xml version="1.0" encoding="utf-8"?><!-- delay           动画延迟时间     animationOrder  子元素动画顺序--><layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"    android:animationOrder="normal"    android:animation="@anim/translate"    android:delay="0.5"></layoutAnimation>


2、指定子元素动画

<?xml version="1.0" encoding="utf-8"?><translate xmlns:android="http://schemas.android.com/apk/res/android"    android:interpolator="@android:anim/accelerate_decelerate_interpolator"    android:duration="300"    android:fromXDelta="500"    android:toXDelta="0"></translate>

3、为ViewGroup指定android:layoutAnimation属性

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical" android:layout_width="match_parent"    android:layout_height="match_parent">    <ListView        android:id="@+id/listView"        android:layout_width="match_parent"        android:layoutAnimation="@anim/anim_layout"        android:layout_height="match_parent"></ListView></LinearLayout>

4、应用

ViewGroup子元素视图

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="horizontal" android:layout_width="match_parent"    android:layout_height="match_parent">    <ImageView        android:src="@mipmap/ic_launcher"        android:layout_width="wrap_content"        android:layout_height="wrap_content" />    <TextView        android:id="@+id/text"        android:layout_marginTop="15dp"        android:layout_width="match_parent"        android:layout_height="wrap_content" /></LinearLayout>

public class TestActivity extends AppCompatActivity {    private ListView listView;    private List<String> s = new ArrayList<>();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.anim_list);        listView = (ListView) findViewById(R.id.listView);        initList();    }    private void initList() {        for(int i = 0 ; i < 10 ; i ++)            s.add("标题" + i);        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this , R.layout.list_item , R.id.text , s);        listView.setAdapter(adapter);    }}



除了通过XML指定layoutAnimation外,也可通过LayoutAnimationController实现

TranslateAnimation translate = (TranslateAnimation) AnimationUtils.loadAnimation(this , R.anim.translate);LayoutAnimationController controller = new LayoutAnimationController(translate);controller.setDelay(1);controller.setOrder(LayoutAnimationController.ORDER_RANDOM);listView.setLayoutAnimation(controller);


2、Activity切换效果



4、视图动画局限性



视图动画仅仅改变了控件的视图位置,并未改变控件的属性,即控件并未移动,只是看起来动了


下面我们做一个测试,打开手机显示布局边界



可以看到,新位置无法触发单击事件,控件真正位置并未移动,为此Android于API 11新加入特性——属性动画




三、属性动画(Animator)


属性动画可以对任何对象做动画

常用属性:

平移          "translationX" \ "translationY"

旋转          "rotation" \ "rotationX" \ "rotationY"

缩放          "scaleX" \ "scaleY"

位置          "X" \ "Y"

透明度      "alpha"

常用的子类有ValueAnimator、ObjectAnimator和AniamtorSet,其中ObjectAnimator继承自ValueAnimator


1、属性动画应用

ObjectAnimator.ofFloat(imageView , "translationX" , 0f , 400f).setDuration(3000).start();ObjectAnimator.ofInt(imageView , "backgroundColor" , 0xFFFF8080 , 0XFF8080FF).setDuration(3000).start();





由以上例子可以看出,属性动画新位置触发了点击事件,即真正改变了控件位置,并且操控了新属性——背景色的变化



其他设置属性动画方法:


-PropertyValuesHodler实现效果与第一种方法一样,优点是其对动画进行了优化,更加节省系统资源

 PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("translationX" , 0f , 400f); PropertyValuesHolder p2 = PropertyValuesHolder.ofInt("backgroundColor" , 0xFFFF8080 , 0XFF8080FF); PropertyValuesHolder p3 = PropertyValuesHolder.ofFloat("rotation" , 0 , 360); ObjectAnimator.ofPropertyValuesHolder(imageView , p1 , p2 , p3).setDuration(3000).start();


-AnimatorSet

ObjectAnimator animator1 = ObjectAnimator.ofFloat(imageView , "translationX" , 0f , 400f);ObjectAnimator animator2 = ObjectAnimator.ofInt(imageView , "backgroundColor" , 0xFFFF8080 , 0XFF8080FF);ObjectAnimator animator3 = ObjectAnimator.ofFloat(imageView , "rotation" , 0 , 360);AnimatorSet set = new AnimatorSet();set.setDuration(3000).start();



2、串行动画


-依次完成

set.playSequentially(animator1 ,animator2 , animator3);//串行动画


-控制完成顺序

set.play(animator1).with(animator3);set.play(animator2).after(animator1);

效果如图,先平移并选择,完成后改变background颜色




当然,属性动画同样可以使用XML定义,位置为res/animator目录下


<?xml version="1.0" encoding="utf-8"?><!-- ordering  动画集合顺序,默认为together--><set    android:ordering="sequentially"    xmlns:android="http://schemas.android.com/apk/res/android">    <!-- propertyName  动画属性         repeatCount   重复次数 默认为 0 无限循环 -1          repeatMode    重复方式 restart 正序  reverse 倒序 -->    <objectAnimator        android:propertyName="translationX"        android:duration="1000"        android:valueFrom="0.0"        android:valueTo="400.0"        android:valueType="floatType">    </objectAnimator>    <objectAnimator        android:propertyName="backgroundColor"        android:duration="1000"        android:valueFrom="@color/colorPrimaryDark"        android:valueTo="@color/colorAccent"        android:repeatCount="-1"        android:repeatMode="reverse"        android:valueType="colorType">    </objectAnimator></set>


使用方法

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(TestActivity1.this , R.animator.animator);set.setTarget(imageView);set.start();


设置监听器

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) {    }});                //AnimatorListenerAdapter可以选择事件animator.addListener(new AnimatorListenerAdapter() {    @Override    public void onAnimationEnd(Animator animation) {        super.onAnimationEnd(animation);    }});                //AnimatorUpdateListener监听整个动画过程,每播放一帧,就会调用一次animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {    @Override    public void onAnimationUpdate(ValueAnimator animation) {    }})



3、ValueAnimator

回到属性动画的特性之一,对任意属性做动画


其需满足

1、对象提供该属性的get和set方法

2、对属性的变化需能通过某种方法反映出来

解决方法

1、给对象加上get和set方法

2、用类包装原始对象,间接提供get和set方法

3、采用ValueAnimator,监听动画过程,实现属性改变


这里我们主要讲解第3种方法

ValueAnimator本身不提供任何动画效果,其作用为一个数值发生器,用来产生具有规律的数字


使用方法:

通过ValueAnimator改变Text属性实现计时器

ValueAnimator animator = ValueAnimator.ofInt(0 , 100);animator.setDuration(5000);animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {     @Override     public void onAnimationUpdate(ValueAnimator animation) {         Integer i = (Integer) animation.getAnimatedValue();         button.setText(i + "");     }});animator.start();


















0 0
原创粉丝点击