先来看效果:
上面为两个按钮,点击对应的按钮,绿色背景会滚动到相应的按钮后面
点击红色方块会有反转效果,仿照win8磁铁的效果
下面是代码
ScrollAnimation.java
package com.iaiai.activity;import android.graphics.Camera;import android.graphics.Matrix;import android.util.Log;import android.view.View;import android.view.animation.Animation;import android.view.animation.LinearInterpolator;import android.view.animation.Transformation;/** * * <br/> * Title: ScrollAnimation.java<br/> * E-Mail: [email protected]<br/> * QQ: 176291935<br/> * Http: iaiai.iteye.com<br/> * Create time: 2013-2-19 上午10:53:06<br/> * <br/> * * @author 丸子 * @version 0.0.1 */public class ScrollAnimation extends Animation { private View view; private Camera camera = new Camera(); private boolean direction = true; // true往右,false往左 public ScrollAnimation(View view, boolean direction) { this.view = view; this.direction = direction; } @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); setDuration(300); setFillAfter(true); setFillBefore(true); setInterpolator(new LinearInterpolator()); } protected void applyTransformation(float interpolatedTime, Transformation transformation) { Matrix matrix = transformation.getMatrix(); camera.save(); if (direction) { camera.translate(interpolatedTime * view.getWidth(), 0.0f, 0); } else { camera.translate(view.getWidth() - (interpolatedTime * view.getWidth()), 0.0f, 0); } camera.getMatrix(matrix); camera.restore(); }}
RotateAnimation.java
package com.iaiai.activity;import android.graphics.Camera;import android.graphics.Matrix;import android.view.View;import android.view.animation.Animation;import android.view.animation.Transformation;/** * * <br/> * Title: RotateAnimation.java<br/> * E-Mail: [email protected]<br/> * QQ: 176291935<br/> * Http: iaiai.iteye.com<br/> * Create time: 2013-2-19 上午10:07:57<br/> * <br/> * * @author 丸子 * @version 0.0.1 */public class RotateAnimation extends Animation { /** 值为true时可明确查看动画的旋转方向。 */ public static final boolean DEBUG = false; /** 沿Y轴正方向看,数值减1时动画逆时针旋转。 */ public static final boolean ROTATE_DECREASE = true; /** 沿Y轴正方向看,数值减1时动画顺时针旋转。 */ public static final boolean ROTATE_INCREASE = false; /** Z轴上最大深度。 */ public static final float DEPTH_Z = 310.0f; /** 动画显示时长。 */ public static final long DURATION = 800l; /** 图片翻转类型。 */ private final boolean type; private final float centerX; private final float centerY; private Camera camera; /** 用于监听动画进度。当值过半时需更新txtNumber的内容。 */ private InterpolatedTimeListener listener; public RotateAnimation(View view, boolean type) { centerX = view.getWidth() / 2.0f; centerY = view.getHeight() / 2.0f; this.type = type; setDuration(DURATION); } public void initialize(int width, int height, int parentWidth, int parentHeight) { // 在构造函数之后、getTransformation()之前调用本方法。 super.initialize(width, height, parentWidth, parentHeight); camera = new Camera(); } public void setInterpolatedTimeListener(InterpolatedTimeListener listener) { this.listener = listener; } protected void applyTransformation(float interpolatedTime, Transformation transformation) { // interpolatedTime:动画进度值,范围为[0.0f,10.f] if (listener != null) { listener.interpolatedTime(interpolatedTime); } float from = 0.0f, to = 0.0f; if (type == ROTATE_DECREASE) { from = 0.0f; to = 180.0f; } else if (type == ROTATE_INCREASE) { from = 360.0f; to = 180.0f; } float degree = from + (to - from) * interpolatedTime; boolean overHalf = (interpolatedTime > 0.5f); if (overHalf) { // 翻转过半的情况下,为保证数字仍为可读的文字而非镜面效果的文字,需翻转180度。 degree = degree - 180; } // float depth = 0.0f; float depth = (0.5f - Math.abs(interpolatedTime - 0.5f)) * DEPTH_Z; final Matrix matrix = transformation.getMatrix(); camera.save(); camera.translate(0.0f, 0.0f, depth); camera.rotateY(degree); camera.getMatrix(matrix); camera.restore(); if (DEBUG) { if (overHalf) { matrix.preTranslate(-centerX * 2, -centerY); matrix.postTranslate(centerX * 2, centerY); } } else { // 确保图片的翻转过程一直处于组件的中心点位置 matrix.preTranslate(-centerX, -centerY); matrix.postTranslate(centerX, centerY); } } /** 动画进度监听器。 */ public static interface InterpolatedTimeListener { public void interpolatedTime(float interpolatedTime); }}
MainActivity.java
package com.iaiai.activity;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.view.animation.AnimationUtils;import android.widget.TextView;import com.iaiai.activity.RotateAnimation.InterpolatedTimeListener;public class MainActivity extends Activity implements OnClickListener, InterpolatedTimeListener { private boolean bol = true; private boolean enableRefresh; private int number = 0; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); findViewById(R.id.btn1).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (!bol) findViewById(R.id.tv).startAnimation(new ScrollAnimation(findViewById(R.id.tv), false)); bol = true; } }); findViewById(R.id.btn2).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (bol) findViewById(R.id.tv).startAnimation(new ScrollAnimation(findViewById(R.id.tv), true)); bol = false; } }); findViewById(R.id.layout1).setOnClickListener(this); } public void onClick(View v) { enableRefresh = true; RotateAnimation rotateAnim = null; if (bol) { number--; rotateAnim = new RotateAnimation(findViewById(R.id.layout1), RotateAnimation.ROTATE_DECREASE); } else { number++; rotateAnim = new RotateAnimation(findViewById(R.id.layout1), RotateAnimation.ROTATE_INCREASE); } if (rotateAnim != null) { rotateAnim.setInterpolatedTimeListener(this); rotateAnim.setFillAfter(true); findViewById(R.id.layout1).startAnimation(rotateAnim); } } @Override public void interpolatedTime(float interpolatedTime) { // 监听到翻转进度过半时,更新txtNumber显示内容。 if (enableRefresh && interpolatedTime > 0.5f) { ((TextView) findViewById(R.id.ltv)).setText(Integer.toString(number)); enableRefresh = false; } }}
main.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@android:color/white" android:orientation="vertical" > <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingBottom="10dip" android:paddingLeft="20dip" android:paddingRight="20dip" android:paddingTop="10dip" > <RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content" > <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:id="@+id/tv" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" android:background="#00ff00" /> <TextView android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" android:textColor="@android:color/black" android:textSize="20dip" android:visibility="invisible" /> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:id="@+id/btn1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" android:gravity="center" android:text="左旋转" android:textColor="@android:color/black" android:textSize="20dip" /> <TextView android:id="@+id/btn2" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" android:gravity="center" android:text="右旋转" android:textColor="@android:color/black" android:textSize="20dip" /> </LinearLayout> </RelativeLayout> </LinearLayout> <LinearLayout android:id="@+id/layout1" android:layout_width="150dip" android:layout_height="150dip" android:background="#ff0000" > <TextView android:id="@+id/ltv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="文字" android:textColor="@android:color/white" android:textSize="20dip" /> </LinearLayout></LinearLayout>