Android动画

一、动画概述


动画作为广泛存在于程序界面中的效果,具有相似的属性,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();


















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值