最近看了淘宝手机端的有些页面是类似下面这个小球的加载效果。后来了解了下,淘宝是直接一个gif图片实现效果的,这当然是最简单的方法。为了加深了解属性动画,这次就做个类似的效果。这依旧由几个简单的属性动画组合在一起,所有动画都在代码里实现了。看注释就好。
上个效果图:
实现代码:
小球圆圈的XML文件 drawable_dot.xml:
<?xml version="1.0"  encoding="utf-8" ?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval"
    >
    <size
        android:height="40dp"
        android:width="40dp"
        />
    <solid
        android:color="#D2691E"
        />
</shape><?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">
    <ImageView
        android:id="@+id/imv_tb_dot1"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_centerInParent="true"
        android:src="@drawable/drawable_dot"
        />
</RelativeLayout>
package com.alextam.circlemoveball;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.media.Image;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
/**
 * @author  Alex Tam
 */
public class MainActivity extends ActionBarActivity {
    private ImageView imv1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imv1= (ImageView)findViewById(R.id.imv_tb_dot1);
        setCircleMoveBall();
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
    /**
     * 设置小球动画
     */
    private void setCircleMoveBall()
    {
        ValueAnimator animatorMove = ValueAnimator.ofInt(0,200);
        animatorMove.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                imv1.setTranslationX((Integer) animation.getAnimatedValue());
            }
        });
        animatorMove.setDuration(1000);
        ValueAnimator animatorMoveScale = ValueAnimator.ofFloat(0.0f,100.0f);
        animatorMoveScale.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (Float)animation.getAnimatedValue();
                //将动画的小球运动分解为2部,当0.0f - 50.0f小球变大,后面一半50.0f-100.0f小球从大恢复正常
                //这里效果看起来是小球从平面向屏幕弹起的样子
                if(value<= 50.0f)
                {
                    imv1.setScaleX(1.0f + value/50);
                    imv1.setScaleY(1.0f + value/50);
                }
                else
                {
                    imv1.setScaleX(1.0f - (value - 100.0f)/50);
                    imv1.setScaleY(1.0f - (value - 100.0f)/50);
                }
            }
        });
        animatorMoveScale.setDuration(1000);
        ValueAnimator animatorBackMove = ValueAnimator.ofInt(200,0);
        animatorBackMove.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                imv1.setTranslationX((Integer) animation.getAnimatedValue());
            }
        });
        animatorBackMove.setDuration(2000);
        ValueAnimator animatorBackScale = ValueAnimator.ofFloat(0.0f,-100.0f);
        animatorBackScale.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (Float)animation.getAnimatedValue();
                float vluA,vluB;
                //同样是将小球分解两步,效果就是动画中的往后变小,透明度逐渐变低,然后恢复正常大小和透明度的效果
                if( value > -50.0f && value < 0)
                {
                    vluA = 1.1f + value/50;
                    imv1.setAlpha(vluA);
                    imv1.setScaleX(vluA);
                    imv1.setScaleY(vluA);
                }
                else
                {
                    vluB = 0.1f - (value + 50.0f)/50;
                    imv1.setAlpha(vluB);
                    imv1.setScaleX(vluB);
                    imv1.setScaleY(vluB);
                }
            }
        });
        animatorBackScale.setDuration(2000);
        final AnimatorSet set = new AnimatorSet();
        //设置几个动画的运动规则
        set.play(animatorMove).with(animatorMoveScale);
        set.play(animatorMoveScale).before(animatorBackMove);
        set.play(animatorBackMove).with(animatorBackScale);
        set.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
            }
            @Override
            public void onAnimationEnd(Animator animation) {
                //在这里实现重复运动
                set.start();
            }
            @Override
            public void onAnimationCancel(Animator animation) {
            }
            @Override
            public void onAnimationRepeat(Animator animation) {
            }
        });
        set.start();
    }
}
原文:http://blog.csdn.net/stzy00/article/details/44545541