基础动画-(1)-补间动画

一.补间动画

1.基本介绍

基本的补间动画分为四个(透明度,缩放,位移,旋转)

(1)AnimationSet

<set>标签对应表示动画集合,对应AnimationSet,他可以包含若干个动画,并且它的内部也是嵌套其他动画的集合,它的两个属性的含义如下:

<1>android:interpolator

android:interpolator  表示动画集合所采用的插值器,插值器影响动画的速度,比如非匀速动画就需要通过设置插值器来控制动画的播放过程,这个属性可以不指定,默认android:anim/accelerate_decelerate_interpolator,即加速减速插值器,关于这个概念后面有篇专门讲这个的文章点我看interpolator


<2>android:shareInterpolator

表示集合中的动画是否和集合共享同一个插值器


(2)<translate>

(3)<scale>

  android:fromXScale    起始的X方向上相对自身的缩放比例,浮点值,比如1.0代表自身无变化,0.5代表起始时缩小一倍,2.0代表放大一倍;

· android:toXScale        结尾的X方向上相对自身的缩放比例,浮点值;

· android:fromYScale    起始的Y方向上相对自身的缩放比例,浮点值,

· android:toYScale        结尾的Y方向上相对自身的缩放比例,浮点值;

· android:pivotX            缩放起点X轴坐标,可以是数值、百分数、百分数三种样式,比如 5050%50%p

当为数值时,表示在当前View的左上角,即原点处加上50px,做为起始缩放点;

如果是50%,表示在当前控件的左上角加上自己宽度的50%做为起始点;

如果是50%p,那么就是表示在当前的左上角加上父控件宽度的50%做为起始点x轴坐标。(具体意义,后面会举例演示)

· android:pivotY           缩放起点Y轴坐标,取值及意义跟android:pivotX一样。

默认轴点是是View的中心

(4)<rotate>

默认轴点是是View的中心

(5)<alapha>


(6)公用的一些api

· android:duration        动画持续时间,以毫秒为单位 

· android:fillAfter          如果设置为true,控件动画结束时,将保持动画最后时的状态(这里的结束指的是自然播放的结束不是手动cancel)

· android:fillBefore       如果设置为true,控件动画结束时,还原到开始动画前的状态(这里的结束指的是自然播放的结束不是手动cancel)

· android:fillEnabled    android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态

· android:repeatCount 重复次数

· android:repeatMode 重复类型,有reverserestart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。

· android:interpolator  设定插值器,其实就是指定的动作效果,后面会讲。


2.效果



3.代码(复杂版)

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener, Animation.AnimationListener {

    private ImageView iv;
    private AlphaAnimation alphaAnimation;
    private ScaleAnimation scaleAnimation;
    private TranslateAnimation transAnimation;
    private RotateAnimation rotateAnimation;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.bt_alpha).setOnClickListener(this);
        findViewById(R.id.bt_rotate).setOnClickListener(this);
        findViewById(R.id.bt_scale).setOnClickListener(this);
        findViewById(R.id.bt_tran).setOnClickListener(this);
        findViewById(R.id.bt_set).setOnClickListener(this);
        findViewById(R.id.bt_stop).setOnClickListener(this);

        iv = (ImageView) findViewById(R.id.iv);

    }


    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.bt_alpha:
                alphaAnimation = new AlphaAnimation(0.0f,0.5f);
                //持续时间长度
                alphaAnimation.setDuration(2000);
                //最后是最终的样子(保持  true,既保持动画最后的效果)
                alphaAnimation.setFillAfter(true);
                //设置持续册数(总共播放次数  变成3!!!!)
                alphaAnimation.setRepeatCount(2);
                //重复的模式//有无限,相反
                alphaAnimation.setRepeatMode(Animation.REVERSE);
                iv.startAnimation(alphaAnimation);
                //监听动画的开始结束
                alphaAnimation.setAnimationListener(this);
                break;
            case R.id.bt_scale:
                //最后是放大缩小的中心点
                //public ScaleAnimation (float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
                //Animation.RELATIVE_TO_SELF  (指的是后面的参数相对于谁) 0.5 就相当于百分之50   1就相当于百分之100
                scaleAnimation = new ScaleAnimation(0.0f, 2.0f, 0.0f, 2.0f,
                        Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                        0.5f);
                //持续时间长度
                scaleAnimation.setDuration(2000);
                //最后是最终的样子(保持  true,既保持动画最后的效果)
                scaleAnimation.setFillAfter(false);
                //设置持续册数
                scaleAnimation.setRepeatCount(2);
                //重复的模式//有无限,相反
                //scaleAnimation.setRepeatMode(Animation.REVERSE);
                iv.startAnimation(scaleAnimation);
                //监听动画的开始结束
                scaleAnimation.setAnimationListener(this);

                break;
            case R.id.bt_tran:
                transAnimation = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0.5f,
                        Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0.5f);
                //持续时间长度
                transAnimation.setDuration(2000);
                //最后是最终的样子(保持  true,既保持动画最后的效果)
                transAnimation.setFillAfter(true);
                //设置持续册数
                transAnimation.setRepeatCount(2);
                //重复的模式//有无限,相反
                transAnimation.setRepeatMode(Animation.REVERSE);
                iv.startAnimation(transAnimation);
                //监听动画的开始结束
                transAnimation.setAnimationListener(this);
                break;
            case R.id.bt_rotate:
                //感觉这里的relative_parent不像是相对屏幕,看清楚到底是相对谁????????
                rotateAnimation = new RotateAnimation(0, 90, Animation.RELATIVE_TO_SELF,
                        0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
                //持续时间长度
                rotateAnimation.setDuration(2000);
                //最后是最终的样子(保持  true,既保持动画最后的效果)
                rotateAnimation.setFillAfter(true);
                //设置持续册数
                rotateAnimation.setRepeatCount(2);
                //重复的模式//有无限,相反
                rotateAnimation.setRepeatMode(Animation.REVERSE);
                iv.startAnimation(rotateAnimation);
                //监听动画的开始结束
                rotateAnimation.setAnimationListener(this);
                break;
            case R.id.bt_set:
                //Pass true if all of the animations in this set should use
                // the interpolator associated with this AnimationSet.
                // Pass false if each animation should use its own interpolator.
                AnimationSet set = new AnimationSet(true);
                TranslateAnimation ta = new TranslateAnimation(
                        Animation.RELATIVE_TO_SELF, -0.5f, Animation.RELATIVE_TO_SELF, 0.5f,
                        Animation.RELATIVE_TO_SELF, -0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
                ta.setDuration(2000);
                ta.setRepeatCount(2);
                ta.setRepeatMode(Animation.REVERSE);
                RotateAnimation ra = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF,
                        0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
                ra.setDuration(2000);
                ra.setRepeatCount(2);
                ra.setRepeatMode(Animation.REVERSE);
                ScaleAnimation sa = new ScaleAnimation(0.0f, 2.0f, 0.0f, 2.0f,
                        Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                        0.5f);
                sa.setDuration(2000);
                sa.setRepeatCount(2);
                sa.setRepeatMode(Animation.REVERSE);
                set.addAnimation(sa);
                set.addAnimation(ta);
                set.addAnimation(ra);
                iv.startAnimation(set);
                break;
            case R.id.bt_stop:
                //停止所有动画
                iv.clearAnimation();
                break;

        }
    }

    @Override
    public void onAnimationStart(Animation animation) {

    }

    @Override
    public void onAnimationEnd(Animation animation) {

    }

    @Override
    public void onAnimationRepeat(Animation animation) {

    }
}


复杂版源码

4.代码(简单版)

MainActivity.java

public class MainActivity extends Activity implements View.OnClickListener, Animation.AnimationListener {

    private ImageView iv;
    private Animation scale;
    private Animation trans;
    private Animation rotate;
    private Animation alpha;
    private Animation set;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.bt_alpha).setOnClickListener(this);
        findViewById(R.id.bt_rotate).setOnClickListener(this);
        findViewById(R.id.bt_scale).setOnClickListener(this);
        findViewById(R.id.bt_tran).setOnClickListener(this);
        findViewById(R.id.bt_set).setOnClickListener(this);
        findViewById(R.id.bt_stop).setOnClickListener(this);

        iv = (ImageView) findViewById(R.id.iv);

    }


    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.bt_alpha:
                alpha = AnimationUtils.loadAnimation(this, R.anim.alpha);
                iv.startAnimation(alpha);

                break;
            case R.id.bt_scale:
                scale = AnimationUtils.loadAnimation(this, R.anim.scale);
                iv.startAnimation(scale);

                break;
            case R.id.bt_tran:
                trans = AnimationUtils.loadAnimation(this, R.anim.trans);
                iv.startAnimation(trans);
                break;
            case R.id.bt_rotate:
                rotate = AnimationUtils.loadAnimation(this, R.anim.rotate);
                iv.startAnimation(rotate);
                break;
            case R.id.bt_set:
                set = AnimationUtils.loadAnimation(this, R.anim.set);
                iv.startAnimation(set);
                break;
            case R.id.bt_stop:
                //停止所有动画
                iv.clearAnimation();
                break;

        }
    }

    @Override
    public void onAnimationStart(Animation animation) {

    }

    @Override
    public void onAnimationEnd(Animation animation) {

    }

    @Override
    public void onAnimationRepeat(Animation animation) {

    }
}


alaph.xml

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="0"
    android:toAlpha="1.0"
    android:duration="2000"
    android:repeatCount="2"
    android:repeatMode="reverse" >
</alpha>

rotate.xml

//rotate.xml(里面P,是代表父控件的意思,没有P,就是指自身)

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="90"
    android:toDegrees="0"
    android:duration="2000"
    android:repeatCount="2"
    android:repeatMode="reverse"
    android:pivotX="20%p"
    android:pivotY="20%p" >

</rotate>
scale.xml
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="2000"
    android:fromXScale="0.0"
    android:fromYScale="0.0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="2"
    android:repeatMode="reverse"
    android:toXScale="2.0"
    android:toYScale="2.0" >

</scale>
tran.xml
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="2000"
    android:fromXDelta="-50%p"
    android:fromYDelta="0%"
    android:repeatCount="2"
    android:repeatMode="reverse"
    android:toXDelta="0%"
    android:fillAfter="true"
    android:toYDelta="50%" >

</translate>
set.xml

<?xml version="1.0" encoding="utf-8"?>
<set>

    <rotate
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="2000"
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="2"
        android:repeatMode="reverse"
        android:toDegrees="360" >
    </rotate>

    <scale
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="2000"
        android:fromXScale="0.0"
        android:fromYScale="0.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="2"
        android:repeatMode="reverse"
        android:toXScale="2.0"
        android:toYScale="2.0" >
    </scale>

    <translate
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="2000"
        android:fromXDelta="-50%"
        android:fromYDelta="-50%"
        android:repeatCount="2"
        android:repeatMode="reverse"
        android:toXDelta="50%"
        android:toYDelta="50%" >
    </translate>

</set>

简单版源码


5.一些问题的分析(reLative_parent,还有Rotate的中心点,不管相对谁(parent还是self)坐标原点都是View的左上角顶点

(1)Rotate的圆心的确定

Rotate.xml(圆心以parent的宽高的1/3)

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:toDegrees="-360"
    android:duration="2000"
    android:repeatCount="2"
    android:repeatMode="reverse"
    android:pivotX="30%p"
    android:pivotY="30%p" >

</rotate>

基础动画-(1)-补间动画_第1张图片

基础动画-(1)-补间动画_第2张图片


Rotate.xml(圆心以parent的宽高的1/3)

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:toDegrees="-360"
    android:duration="2000"
    android:repeatCount="2"
    android:repeatMode="reverse"
    android:pivotX="50%"
    android:pivotY="50%" >

</rotate>
基础动画-(1)-补间动画_第3张图片

基础动画-(1)-补间动画_第4张图片


(2)Rotate的旋转方向的确定(顺时针逆时针都是围绕自身)

<1>

<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:toDegrees="180"
    android:duration="2000"
    android:fillAfter="true"
    android:pivotX="50%"
    android:pivotY="50%" >
</rotate>
<2>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:toDegrees="-180"
    android:duration="2000"
    android:fillAfter="true"
    android:pivotX="50%"
    android:pivotY="50%" >
</rotate>

<1>顺时针  (0到180) <1>时针  (0到180)

基础动画-(1)-补间动画_第5张图片                                               

6.帧动画

FrameAnimation.xml

<?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/girl_1" android:duration="100"/>
    <item android:drawable="@drawable/girl_2" android:duration="100"/>
    <item android:drawable="@drawable/girl_3" android:duration="100"/>
    <item android:drawable="@drawable/girl_4" android:duration="100"/>
    <item android:drawable="@drawable/girl_5" android:duration="100"/>
    <item android:drawable="@drawable/girl_6" android:duration="100"/>
    <item android:drawable="@drawable/girl_7" android:duration="100"/>
    <item android:drawable="@drawable/girl_8" android:duration="100"/>
    <item android:drawable="@drawable/girl_9" android:duration="100"/>
    <item android:drawable="@drawable/girl_10" android:duration="100"/>
    <item android:drawable="@drawable/girl_11" android:duration="100"/>
</animation-list>


MainActivity.java
public class MainActivity extends AppCompatActivity {

    private Button bt_one;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bt_one = (Button) findViewById(R.id.bt_one);
    }

    public void startAnimation(View view){
        bt_one.setBackgroundResource(R.drawable.frame_animation);
        AnimationDrawable drawable = (AnimationDrawable) bt_one.getBackground();
        drawable.start();
    }
}

简单帧动画实现源码


7.简单应用


(1).效果图

基础动画-(1)-补间动画_第6张图片


(2)主要代码

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private ImageView iv_slow;
    private ImageView iv_faster;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        iv_slow = (ImageView) findViewById(R.id.img_home_cloud_move_slower);
        iv_faster = (ImageView) findViewById(R.id.img_home_cloud_move_faster);
        findViewById(R.id.bt_start).setOnClickListener(this);

    }


    @Override
    public void onClick(View v) {
        if(v.getId()  == R.id.bt_start){
            Animation slower = AnimationUtils.loadAnimation(this,R.anim.home_cloud_animation_slower);
            iv_slow.startAnimation(slower);
            Animation faster = AnimationUtils.loadAnimation(this,R.anim.home_cloud_animation_fater);
            iv_faster.startAnimation(faster);
        }
    }
}

faset.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="100%p"
        android:toXDelta="-20%p"
        android:interpolator="@android:anim/linear_interpolator"
        android:repeatCount="infinite"
        android:duration="30000" />
</set>


slower.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="100%p"
        android:toXDelta="-20%p"
        android:interpolator="@android:anim/linear_interpolator"
        android:repeatCount="infinite"
        android:duration="20000" />
</set>

8.View动画的特殊使用场景

(1)LayoutAnimation

LayoutAnimation给ViewGroup指定一个动画,那么他的子View也会是这个动画

<1>定义一个LayoutAnimation,如下所示。

anim_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
       android:delay = "0.5"
       android:animationOrder="random"
       android:animation = "@anim/anim_item"/>

<!--android:delay = "10" 這個10 指的是anim_itemduration的倍數,這裡就相當於10*0.3 = 3 相当于每隔3s就播放一次动画--> <!--android:animationOrder="random" 有三种normal reverse random  其中normal:按顺序显示 ,既前面的条目先播放  其中reverse:既排在后面的子元素先开始播放入场动画  random 则是随机播放入场动画-->
android:animation 为子元素指定具体的入场动画

<2>为子元素指定具体的入场动画,如下所示

anim_item.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:shareInterpolator="true"
    android:interpolator="@android:anim/accelerate_interpolator">

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

    <translate
        android:fromXDelta="500"
        android:toXDelta="0"
        />
</set>

<3>为viewGroup指定android:layoutAnimation 属性

   <ListView
        android:id="@+id/lv"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layoutAnimation="@anim/anim_layout">
    </ListView>

注意:还可以使用方法二通过LayoutAnimationController来实现

  Animation animation = AnimationUtils.loadAnimation(this,R.anim.anim_item);
        LayoutAnimationController controller = new LayoutAnimationController(animation);
        controller.setDelay(0.3f);
        controller.setOrder(LayoutAnimationController.ORDER_RANDOM);
        lv.setLayoutAnimation(controller);

LayoutAnimation基本使用的源码


9.Activity的切换效果

Activity有默认的切换效果,但是这个效果我们可以自定义的,主要用到overridePendingTransition(int enterAnim,int exitAnim)这个方法,这个方法必须在startActivity或者finish()之后调用才能生效(否则无效)。

BaseActivity.java

public abstract class BaseActivity extends Activity {
    private GestureDetector mGestureDetector;
    public SharedPreferences sp;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_base);
        sp = getSharedPreferences("config", MODE_PRIVATE);

        //完成手势滑动
        //SimpleOnGestureListener//相当于阉割版
        //		A convenience class to extend when you only want to listen for a subset of all the gestures.
        //		This implements all methods in the OnGestureListener and OnDoubleTapListener
        //		but does nothing and return false for all applicable methods
        mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2,
                                   float velocityX, float velocityY) {
                //首先先排除无效动作,比如数值方向滑动//我们要求尽可能的水平滑动
                if (e1.getRawY() - e2.getRawY() > 100) {
                    Toast.makeText(BaseActivity.this, "请正确姿势滑动。。。水平滑动!!!", Toast.LENGTH_SHORT).show();
                    return true;
                }
                //判断如果是左<--------右
                if (e1.getRawX() - e2.getRawX() > 150) {
                    showNext();
                    overridePendingTransition(R.anim.tran_next_in, R.anim.tran_next_out);
                    return true;
                }
                //判断如果是左------->右
                if (e2.getRawX() - e1.getRawX() > 150) {
                    showPre();
                    overridePendingTransition(R.anim.tran_pre_in, R.anim.tran_pre_out);
                    return true;
                }
                return super.onFling(e1, e2, velocityX, velocityY);
            }
        });


    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //别忘了这个
        mGestureDetector.onTouchEvent(event);
        return super.onTouchEvent(event);
    }

    /**
     * 给出上下两个函数让子类继承然后覆写功能
     */
    public abstract void showNext();

    public abstract void showPre();


    /**
     * 让子类直接继承调用就行
     * 功能showNext()
     * 动画overridePendingTransition
     * 不要忘了写View view
     */
    public void next(View view) {
        showNext();
        overridePendingTransition(R.anim.tran_next_in, R.anim.tran_next_out);

    }

    /**
     * 让子类直接继承调用就行
     * 功能showNext()
     * 动画overridePendingTransition
     * 不要忘了写View view
     */
    public void pre(View view) {

        showPre();
        overridePendingTransition(R.anim.tran_pre_in, R.anim.tran_pre_out);

    }

}

tran_next_in.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
   android:fromXDelta="100%p"
    android:toXDelta="0"
    android:fromYDelta="0"
    android:toYDelta="0"
    android:duration="300"
    >
</translate>


MainActivity.java

public class MainActivity extends BaseActivity {

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

    @Override
    public void showNext() {
        Intent intent = new Intent(this,SecondActivity.class);
        startActivity(intent);
    }

    @Override
    public void showPre() {
        Toast.makeText(MainActivity.this,"到头了",Toast.LENGTH_SHORT).show();
    }

}

源码在这


你可能感兴趣的:(基础动画-(1)-补间动画)