其功能和android.animation.*中的类的功能完全一致,使用方法完全一样,只要我们用nineoldandroids来编写动画,就可以在所有的Android系统上运行。比较常用的几个动画类是:ValueAnimator、ObjectAnimator和AnimatorSet,其中ObjectAnimator继承自ValueAnimator,AnimatorSet是动画集,可以定义一组动画。使用起来也是及其简单的,下面举几个小栗子。
栗子1:改变一个对象(myObject)的 translationY属性,让其沿着Y轴向上平移一段距离:它的高度,该动画在默认时间内完成,动画的完成时间是可以定义的,想要更灵活的效果我们还可以定义插值器和估值算法,但是一般来说我们不需要自定义,系统已经预置了一些,能够满足常用的动画。
ObjectAnimator.ofFloat(myObject, translationY, -myObject.getHeight()).start();
栗子2:改变一个对象的背景色属性,典型的情形是改变View的背景色,下面的动画可以让背景色在3秒内实现从0xFFFF8080到0xFF8080FF的渐变,并且动画会无限循环而且会有反转的效果
ValueAnimator colorAnim = ObjectAnimator.ofInt(this, backgroundColor, /*Red*/0xFFFF8080, /*Blue*/0xFF8080FF);
colorAnim.setDuration(3000);
colorAnim.setEvaluator(new ArgbEvaluator());
colorAnim.setRepeatCount(ValueAnimator.INFINITE);
colorAnim.setRepeatMode(ValueAnimator.REVERSE);
colorAnim.start();
栗子3:动画集合,5秒内对View的旋转、平移、缩放和透明度都进行了改变
AnimatorSet set = new AnimatorSet();
set.playTogether(
ObjectAnimator.ofFloat(myView, rotationX, 0, 360),
ObjectAnimator.ofFloat(myView, rotationY, 0, 180),
ObjectAnimator.ofFloat(myView, rotation, 0, -90),
ObjectAnimator.ofFloat(myView, translationX, 0, 90),
ObjectAnimator.ofFloat(myView, translationY, 0, 90),
ObjectAnimator.ofFloat(myView, scaleX, 1, 1.5f),
ObjectAnimator.ofFloat(myView, scaleY, 1, 0.5f),
ObjectAnimator.ofFloat(myView, alpha, 1, 0.25f, 1)
);
set.setDuration(5 * 1000).start();
栗子4:下面是个简单的调用方式,其animate方法是nineoldandroids特有的
Button myButton = (Button)findViewById(R.id.myButton);
//Note: in order to use the ViewPropertyAnimator like this add the following import:
// import static com.nineoldandroids.view.ViewPropertyAnimator.animate;
animate(myButton).setDuration(2000).rotationYBy(720).x(100).y(100);
栗子5:一个采用nineoldandroids实现的稍微复杂点的动画
布局xml如下:
<framelayout android:layout_height="match_parent" android:layout_width="match_parent" xmlns:android="http://schemas.android.com/apk/res/android">
</framelayout>
代码如下:
public class MainActivity extends Activity implements OnClickListener {
private static final String TAG = MainActivity;
private Button mMenuButton;
private Button mItemButton1;
private Button mItemButton2;
private Button mItemButton3;
private Button mItemButton4;
private Button mItemButton5;
private boolean mIsMenuOpen = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void initView() {
mMenuButton = (Button) findViewById(R.id.menu);
mMenuButton.setOnClickListener(this);
mItemButton1 = (Button) findViewById(R.id.item1);
mItemButton1.setOnClickListener(this);
mItemButton2 = (Button) findViewById(R.id.item2);
mItemButton2.setOnClickListener(this);
mItemButton3 = (Button) findViewById(R.id.item3);
mItemButton3.setOnClickListener(this);
mItemButton4 = (Button) findViewById(R.id.item4);
mItemButton4.setOnClickListener(this);
mItemButton5 = (Button) findViewById(R.id.item5);
mItemButton5.setOnClickListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
mMenuButton.performClick();
getMenuInflater().inflate(R.menu.main, menu);
return false;
}
@Override
public void onClick(View v) {
if (v == mMenuButton) {
if (!mIsMenuOpen) {
mIsMenuOpen = true;
doAnimateOpen(mItemButton1, 0, 5, 300);
doAnimateOpen(mItemButton2, 1, 5, 300);
doAnimateOpen(mItemButton3, 2, 5, 300);
doAnimateOpen(mItemButton4, 3, 5, 300);
doAnimateOpen(mItemButton5, 4, 5, 300);
} else {
mIsMenuOpen = false;
doAnimateClose(mItemButton1, 0, 5, 300);
doAnimateClose(mItemButton2, 1, 5, 300);
doAnimateClose(mItemButton3, 2, 5, 300);
doAnimateClose(mItemButton4, 3, 5, 300);
doAnimateClose(mItemButton5, 4, 5, 300);
}
} else {
Toast.makeText(this, 你点击了 + v, Toast.LENGTH_SHORT).show();
}
}
/**
* 打开菜单的动画
* @param view 执行动画的view
* @param index view在动画序列中的顺序
* @param total 动画序列的个数
* @param radius 动画半径
*/
private void doAnimateOpen(View view, int index, int total, int radius) {
if (view.getVisibility() != View.VISIBLE) {
view.setVisibility(View.VISIBLE);
}
double degree = Math.PI * index / ((total - 1) * 2);
int translationX = (int) (radius * Math.cos(degree));
int translationY = (int) (radius * Math.sin(degree));
Log.d(TAG, String.format(degree=%f, translationX=%d, translationY=%d,
degree, translationX, translationY));
AnimatorSet set = new AnimatorSet();
//包含平移、缩放和透明度动画
set.playTogether(
ObjectAnimator.ofFloat(view, translationX, 0, translationX),
ObjectAnimator.ofFloat(view, translationY, 0, translationY),
ObjectAnimator.ofFloat(view, scaleX, 0f, 1f),
ObjectAnimator.ofFloat(view, scaleY, 0f, 1f),
ObjectAnimator.ofFloat(view, alpha, 0f, 1));
//动画周期为500ms
set.setDuration(1 * 500).start();
}
/**
* 关闭菜单的动画
* @param view 执行动画的view
* @param index view在动画序列中的顺序
* @param total 动画序列的个数
* @param radius 动画半径
*/
private void doAnimateClose(final View view, int index, int total,
int radius) {
if (view.getVisibility() != View.VISIBLE) {
view.setVisibility(View.VISIBLE);
}
double degree = Math.PI * index / ((total - 1) * 2);
int translationX = (int) (radius * Math.cos(degree));
int translationY = (int) (radius * Math.sin(degree));
Log.d(TAG, String.format(degree=%f, translationX=%d, translationY=%d,
degree, translationX, translationY));
AnimatorSet set = new AnimatorSet();
//包含平移、缩放和透明度动画
set.playTogether(
ObjectAnimator.ofFloat(view, translationX, translationX, 0),
ObjectAnimator.ofFloat(view, translationY, translationY, 0),
ObjectAnimator.ofFloat(view, scaleX, 1f, 0f),
ObjectAnimator.ofFloat(view, scaleY, 1f, 0f),
ObjectAnimator.ofFloat(view, alpha, 1f, 0f));
//为动画加上事件监听,当动画结束的时候,我们把当前view隐藏
set.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
@Override
public void onAnimationEnd(Animator animator) {
view.setVisibility(View.GONE);
}
@Override
public void onAnimationCancel(Animator animator) {
}
});
set.setDuration(1 * 500).start();
}
}