1、动画(Animation)
传统动画中,有位移、旋转、缩放、透明度变化等动画,如以下代码移动一个图片控件
TranslateAnimation animation = new TranslateAnimation(0, 200, 0, 0);animation.setDuration(1000);animation.setFillAfter(true);//使控件停留到动画结束的位置,若不设置则返回原来位置iv.startAnimation(animation);
但iv的属性却留在了原地。iv的事件响应只在原来位置生效。而属性动画这可以实现属性随控件移动,如下句:
ObjectAnimator.ofFloat(iv, "translationX", 0, 200).setDuration(1000).start();
这句与以上代码会有相同的动画效果,且iv的响应事件也会跟随控件移动。
translationX或者translationY都是指控件的偏移量,也可以使用X,Y 指的是控件位置变化,如下句:
ObjectAnimator.ofFloat(iv, "Y", 0, 200).setDuration(1000).start();
这个方法的第二个参数是指控件中有get,set方法的属性名。只要有get与set方法就可以使用这种方法操作。如下句:
ObjectAnimator.ofFloat(iv, "rotation", 0, 360).setDuration(1000).start();
翻转360度
而若这三个动画放到一起,如下:
ObjectAnimator.ofFloat(iv, "rotation", 0, 360).setDuration(1000).start();ObjectAnimator.ofFloat(iv, "Y", 0, 200).setDuration(1000).start();ObjectAnimator.ofFloat(iv, "translationX", 0, 200).setDuration(1000).start();
则图片将会同时执行这三个动画,而不会执行一个后在执行另一个。这种效果也可以用以下方式;
PropertyValuesHolder p1=PropertyValuesHolder.ofFloat("rotation", 0, 360);PropertyValuesHolder p2=PropertyValuesHolder.ofFloat( "Y", 0, 200);PropertyValuesHolder p3=PropertyValuesHolder.ofFloat("translationX", 0, 200); ObjectAnimator.ofPropertyValuesHolder(iv,p1,p2,p3).setDuration(1000).start();
以下也同样可以做到
ObjectAnimator a1 = ObjectAnimator.ofFloat(iv, "rotation", 0, 360);ObjectAnimator a2 = ObjectAnimator.ofFloat(iv, "Y", 0, 200);ObjectAnimator a3 = ObjectAnimator.ofFloat(iv, "translationX", 0, 200); AnimatorSet set = new AnimatorSet();set.playTogether(a1,a2,a3);set.setDuration(1000);set.start();
以上三种方法都是三个动画同时执行,若要按照顺序执行,这应该为:
ObjectAnimator a1 = ObjectAnimator.ofFloat(iv, "rotation", 0, 360);ObjectAnimator a2 = ObjectAnimator.ofFloat(iv, "Y", 0, 200);ObjectAnimator a3 = ObjectAnimator.ofFloat(iv, "translationX", 0, 200); AnimatorSet set = new AnimatorSet();set.playSequentially(a1,a2,a3);set.setDuration(1000);set.start();
当然也可以指定动画配合,设置几个同时执行,或者执行一个后在执行另外两个,如以下:
ObjectAnimator a1 = ObjectAnimator.ofFloat(iv, "rotation", 0, 360);ObjectAnimator a2 = ObjectAnimator.ofFloat(iv, "Y", 0, 200);ObjectAnimator a3 = ObjectAnimator.ofFloat(iv, "translationX", 0, 200);AnimatorSet set = new AnimatorSet();set.play(a1).with(a2).before(a3);set.setDuration(1000);set.start();
导致的效果就是,先旋转并向下,之后在向右移动
添加属性动画的监听事件:
ObjectAnimator a4 = ObjectAnimator.ofFloat(iv, "alpha", 0, 1); a4.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { LLogUtils.log(); } @Override public void onAnimationEnd(Animator animation) { LLogUtils.log(); ToastUtil.show("结束了!!"); } @Override public void onAnimationCancel(Animator animation) { LLogUtils.log(); } @Override public void onAnimationRepeat(Animator animation) { LLogUtils.log(); }}); a4.setDuration(1000);a4.start();
或者使用另一种无需全部实现的listener
ObjectAnimator a4 = ObjectAnimator.ofFloat(iv, "alpha", 0, 1); a4.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { ToastUtil.show("结束了"); LLogUtils.log(); }}); a4.setDuration(1000);a4.start();
这样,可以自己选择要处理的事件并重写指定的方法,一般是结束时的事件。
下面,是一个实例,展示多个如元优酷APP的菜单的展开和回收,先看效果图。
就是这样一个效果。
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:padding="20dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:src="@drawable/h"
android:id="@+id/iv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
android:src="@drawable/g"
android:id="@+id/iv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/iv3"
android:src="@drawable/f"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
android:src="@drawable/e"
android:id="@+id/iv4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
android:src="@drawable/d"
android:id="@+id/iv5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
android:src="@drawable/c"
android:id="@+id/iv6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
android:src="@drawable/b"
android:id="@+id/iv7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
android:src="@drawable/a"
android:id="@+id/iv8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</FrameLayout>
代码文件:
package com.linwoain.test; import android.animation.ObjectAnimator;import android.os.Bundle;import android.view.View;import android.view.animation.AccelerateInterpolator;import android.view.animation.BounceInterpolator;import android.widget.ImageView;import com.linwoain.ui.LinActivity;import com.linwoain.util.LLogUtils;import com.linwoain.util.ToastUtil; import java.util.ArrayList;import java.util.List; public class MainActivity extends LinActivity implements View.OnClickListener { private int[] res = {R.id.iv8, R.id.iv1, R.id.iv2, R.id.iv3, R.id.iv4, R.id.iv5, R.id.iv6, R.id.iv7}; private List<ImageView> imageViews = new ArrayList<ImageView>(); private boolean flag=true; /** * Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); LLogUtils.log(); for (int i = 0; i < res.length; i++) { ImageView iv = (ImageView) findViewById(res[i]); iv.setOnClickListener(this); imageViews.add(iv); } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.iv8: if (flag) { startAnim(); } else { closeAnim(); } break; default: ToastUtil.show(v.hashCode()+""); break; } } private void closeAnim() { for (int i = 1; i < res.length; i++) { ObjectAnimator animator = ObjectAnimator.ofFloat(imageViews.get(i), "translationY", 110 * i, 0); animator.setDuration(500); animator.setStartDelay(i * 300); animator.start(); animator.setInterpolator(new AccelerateInterpolator()); } flag = true; } private void startAnim() { for (int i = 1; i < res.length; i++) { ObjectAnimator animator = ObjectAnimator.ofFloat(imageViews.get(i), "translationY", 0, 110 * i); animator.setDuration(500); animator.setStartDelay(i * 300); animator.setInterpolator(new BounceInterpolator());//插值器 animator.start(); } flag=false; }}
注意,动画中可以设置插值器,以实现特殊的效果,如动画运行中加速,减速,回弹等。可以参考apidemos中animation中的Interpolator
时间: 2024-10-29 00:21:09