android平台下,动画实现Metro动态磁贴特效

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012496623/article/details/38388155

网上有很多Win8动态磁贴特效的代码,但是都是使用基于继承ImageView的自定义类,这种实现方法有一个短板就是该类要实现Metro特效必须是以图片为背景的,而且scaleType必须只能指定为matrix。不然特效就出不来。

自己参考了网上的代码很久,自己琢磨出来了使用动画来实现Metro特效,通过继承自Animation来重写里面的protected void applyTransformation(float interpolatedTime, Transformation t)、public boolean getTransformation(long currentTime, Transformation outTransformation)和public void initialize(int width, int height, int parentWidth, int parentHeight) 方法实现的,废话不多说,上代码:

自定义动画类:

<pre name="code" class="java">package com.hwlong.Utils;

import android.graphics.Camera;
import android.graphics.Matrix;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.Transformation;

/**
 * 动态磁贴动画
 * 
 * @author HeJie
 * 
 */
public class MetroAnimation extends Animation {

	private int touchX;  //触控X坐标
	private int touchY;  //触控Y坐标
	private int mHeight; //View的高度
	private int mWidth;  //View的宽度
	private int count;
	private View view; //动画对应的View
	private boolean XbigY = false;
	private boolean isScale = false;  //true使用放缩特效,false则使用反转特效

	private boolean mPaused = false;
	private boolean isPause = true;
	private long mElapsedAtPause = 0;

	private float RotateX = 0;
	private float RotateY = 0;
	private float minK = 0.012f;  //放缩函数的斜率

	private Camera camera;

	public MetroAnimation() {
		super();
		camera = new Camera();
	}

	/**
	 * 设置点击的位置、viewID等信息
	 * @param touchX
	 * @param touchY
	 * @param ViewID
	 */
	public void setTouchPoint(int touchX, int touchY, View view) {
		this.touchX = touchX;
		this.touchY = touchY;
		this.view = view;
	}
	
	@Override
	protected void applyTransformation(float interpolatedTime, Transformation t) {
		super.applyTransformation(interpolatedTime, t);

		if (isScale) {
			if (!mPaused) {
				float s = 0;
				if (count < 10) {
					//根据count的值 计算放缩率s的值
					s = (1f - count * minK);
					BeginScale(t.getMatrix(), s);
				} else if (count < 20) {
					//放缩特效执行一半时,自动暂停
					if (count == 10 && isPause) {
						Pause();
					}
					s = 1f + (count - 19) * minK;
					BeginScale(t.getMatrix(), s);
				} else {
					view.clearAnimation();
				}
				count++;
			} else {
				//暂停时缩小矩阵至最小状态
				BeginScale(t.getMatrix(), (1f - 10 * minK));
			}
		} else {
			if (!mPaused) {
				if (count < 10) {
					//count为旋转的角度
					BeginRotate(t.getMatrix(), (XbigY ? count : 0), (XbigY ? 0
							: count));
				} else if (count <= 20) {
					//旋转特效执行一半时,自动暂停
					if (count == 10 && isPause) {
						Pause();
					}
					//(20 - count)为旋转的角度值
					BeginRotate(t.getMatrix(), (XbigY ? 20 - count : 0),
							(XbigY ? 0 : 20 - count));
				} else {
					view.clearAnimation();
				}
				count += 2;
			} else {
				//暂停时旋转矩阵至最大状态
				BeginRotate(t.getMatrix(), (XbigY ? 10 : 0), (XbigY ? 0 : 10));
			}
		}

	}

	@Override
	public boolean getTransformation(long currentTime,
			Transformation outTransformation) {
		//设置暂停后第一次调用该方法,记录暂停时用过的时间
		if (mPaused && mElapsedAtPause == 0) {
			mElapsedAtPause = currentTime - getStartTime();
		}
		if (mPaused)
			//设置开始时间,不然动画会随暂停的时间流逝而停止
			setStartTime(currentTime - mElapsedAtPause);
		return super.getTransformation(currentTime, outTransformation);
	}

	/**
	 * 暂停动画
	 */
	public void Pause() {
		mElapsedAtPause = 0;
		mPaused = true;
	}

	/**
	 * 恢复动画
	 */
	public void Resume() {
		mPaused = false;
		isPause = false;
	}

	@Override
	public void initialize(int width, int height, int parentWidth,
			int parentHeight) {
		super.initialize(width, height, parentWidth, parentHeight);
		mWidth = width;
		mHeight = height;
		count = 0;
		isPause = true;
		RotateX = mWidth / 2 - touchX;
		RotateY = mHeight / 2 - touchY;
		XbigY = Math.abs(RotateX) > Math.abs(RotateY) ? true : false;
		isScale = touchX > mWidth / 3 && touchX < mWidth / 3 * 2
				&& touchY > mHeight / 3 && touchY < mHeight / 3 * 2;
		setDuration(500);
		setFillAfter(true);
		setFillBefore(false);
		setInterpolator(new LinearInterpolator());
	}

	public int getViewID() {
		return view.getId();
	}
	
	/**
	 * 旋转效果
	 * @param matrix
	 * @param rotateX 绕X轴的旋转角度
	 * @param rotateY 绕Y轴的旋转角度
	 */
	private synchronized void BeginRotate(Matrix matrix, float rotateX,
			float rotateY) {
		int scaleX = (int) (mWidth * 0.5);
		int scaleY = (int) (mHeight * 0.5);
		camera.save();
		camera.rotateX(RotateY > 0 ? rotateY : -rotateY);
		camera.rotateY(RotateX < 0 ? rotateX : -rotateX);
		camera.getMatrix(matrix);
		camera.restore();

		if (RotateX > 0 && rotateX != 0) {
			matrix.preTranslate(-mWidth, -scaleY);
			matrix.postTranslate(mWidth, scaleY);
		} else if (RotateY > 0 && rotateY != 0) {
			matrix.preTranslate(-scaleX, -mHeight);
			matrix.postTranslate(scaleX, mHeight);
		} else if (RotateX < 0 && rotateX != 0) {
			matrix.preTranslate(0, -scaleY);
			matrix.postTranslate(0, scaleY);
		} else if (RotateY < 0 && rotateY != 0) {
			matrix.preTranslate(-scaleX, 0);
			matrix.postTranslate(scaleX, 0);
		}
	}

	/**
	 * 放缩效果
	 * @param matrix
	 * @param scale 放缩率 大于1放大,小于1缩小
	 */
	private synchronized void BeginScale(Matrix matrix, float scale) {
		int scaleX = (int) (mWidth * 0.5);
		int scaleY = (int) (mHeight * 0.5);
		matrix.postScale(scale, scale, scaleX, scaleY);
	}
	
	public int getmHeight() {
		return mHeight;
	}

	public int getmWidth() {
		return mWidth;
	}

}


主界面类:


package com.hwlong.Activity;

import com.hwlong.Utils.MetroAnimation;
import com.hwlong.Activity.R;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.widget.RelativeLayout;

/**
 * 主界面类
 * @author HeJie
 *
 */
public class MainActivity extends Activity {

	private OnTouchListener metroLisener;  //磁贴点击监听器
	private MetroAnimation metroAnim;   //Metro特效动画
	private AnimationListener animListener;  //动画监听器
	private boolean isInside = true;    //标记用户点击后是否移出磁贴范围
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		animListener = new AnimationListener() {

			@Override
			public void onAnimationStart(Animation animation) {}

			@Override
			public void onAnimationRepeat(Animation animation) {}

			//动画结束时,转跳对应的Activity
			@Override
			public void onAnimationEnd(Animation animation) {
				//如果未超出磁贴范围才进行转跳
				if (isInside) {
					int id = ((MetroAnimation) animation).getViewID();
					switch (id) {
					case R.id.weather_query:
						startActivity(new Intent(MainActivity.this, WeatherActivity.class));
						break;
					case R.id.noteBook:
						startActivity(new Intent(MainActivity.this, Note_Activity.class));
						break;
					case R.id.kuaidi_search:
						startActivity(new Intent(MainActivity.this, Express_Activity.class));
						break;
					case R.id.contacts:
						startActivity(new Intent(MainActivity.this, Address_Book.class));
						break;
					case R.id.calculator:
						startActivity(new Intent(MainActivity.this, calculator.class));
						break;
					case R.id.calender:
						startActivity(new Intent(MainActivity.this, CalendarActivity.class));
						break;
					case R.id.about:
						startActivity(new Intent(MainActivity.this, About_Activity.class));
						break;
					default:
						break;
					}
				}
			}
		};
		
		//磁贴View的Touch监听器
		metroLisener = new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					int X = (int) event.getX();
					int Y = (int) event.getY();
					metroAnim.setTouchPoint(X, Y, v);
					v.startAnimation(metroAnim);
					isInside = true;
					return true;
				case MotionEvent.ACTION_MOVE:
					int x = (int) event.getX();
					int y = (int) event.getY();
					//超出磁贴范围
					if (x > v.getWidth() || y > v.getHeight() || x < 0 || y < 0) {
						isInside = false;
					} else {
						isInside = true;
					}
					break;
				case MotionEvent.ACTION_UP:
					metroAnim.Resume();
					return false;
				default:
					break;
				}
				return false;
			}
		};

		metroAnim = new MetroAnimation();
		metroAnim.setAnimationListener(animListener);
		
		RelativeLayout weather = (RelativeLayout) findViewById(R.id.weather_query);
		weather.setOnTouchListener(metroLisener);

		RelativeLayout noteBook = (RelativeLayout) findViewById(R.id.noteBook);
		noteBook.setOnTouchListener(metroLisener);

		RelativeLayout kuaidi_search = (RelativeLayout) findViewById(R.id.kuaidi_search);
		kuaidi_search.setOnTouchListener(metroLisener);

		RelativeLayout content = (RelativeLayout) findViewById(R.id.contacts);
		content.setOnTouchListener(metroLisener);

		RelativeLayout calculator = (RelativeLayout) findViewById(R.id.calculator);
		calculator.setOnTouchListener(metroLisener);

		RelativeLayout calender = (RelativeLayout) findViewById(R.id.calender);
		calender.setOnTouchListener(metroLisener);

		RelativeLayout about = (RelativeLayout) findViewById(R.id.about);
		about.setOnTouchListener(metroLisener);
	}

}



主界面布局文件代码:(布局写的不好,父控件和自控件都用了weight,有好的布局方案的欢迎指教)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/MainLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:baselineAligned="false"
    android:orientation="horizontal"
    android:padding="2dp"
    tools:context="com.hwlong.Activity.MainActivity" >

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="vertical" >

        <RelativeLayout
            android:id="@+id/weather_query"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_margin="2dp"
            android:layout_weight="5"
            android:background="@drawable/homepage_bg_weather" >

            <ImageView
                android:id="@+id/imageView1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_alignParentTop="true"
                android:layout_margin="10dp"
                android:contentDescription="@string/image_string"
                android:src="@drawable/homepage_logo_weather" />

            <TextView
                style="@style/homepageText"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hp_weather" />
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/noteBook"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_margin="2dp"
            android:layout_weight="4"
            android:background="@drawable/homepage_bg_notebook" >

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_alignParentTop="true"
                android:layout_margin="10dp"
                android:contentDescription="@string/image_string"
                android:src="@drawable/homepage_logo_notebook" />
            
            <TextView
                style="@style/homepageText"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hp_noteBook" />
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/kuaidi_search"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_margin="2dp"
            android:layout_weight="5"
            android:background="@drawable/homepage_bg_search" >

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_alignParentTop="true"
                android:layout_margin="10dp"
                android:contentDescription="@string/image_string"
                android:src="@drawable/homepage_logo_search" />
            
            <TextView
                style="@style/homepageText"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hp_kuaidi" />
        </RelativeLayout>
    </LinearLayout>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="vertical" >

        <RelativeLayout
            android:id="@+id/contacts"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_margin="2dp"
            android:layout_weight="7"
            android:background="@drawable/homepage_bg_contents" >

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_alignParentTop="true"
                android:layout_margin="10dp"
                android:contentDescription="@string/image_string"
                android:src="@drawable/homepage_logo_contents" />
            <TextView
                style="@style/homepageText"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hp_contacts" />
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/calculator"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_margin="2dp"
            android:layout_weight="7"
            android:background="@drawable/homepage_bg_calculator" >

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_alignParentTop="true"
                android:layout_margin="10dp"
                android:contentDescription="@string/image_string"
                android:src="@drawable/homepage_logo_calculator" />
            <TextView
                style="@style/homepageText"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hp_calculator" />
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/calender"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_margin="2dp"
            android:layout_weight="8"
            android:background="@drawable/homepage_bg_calendar" >

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_alignParentTop="true"
                android:layout_margin="10dp"
                android:contentDescription="@string/image_string"
                android:src="@drawable/homepage_logo_calendar" />
            <TextView
                style="@style/homepageText"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hp_calender" />
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/about"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_margin="2dp"
            android:layout_weight="3"
            android:background="@drawable/homepage_bg_about" >

            <ImageView
                android:id="@+id/imageView2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_alignParentTop="true"
                android:layout_margin="10dp"
                android:contentDescription="@string/image_string"
                android:src="@drawable/homepage_logo_about" />

            <TextView
                android:textColor="#FFFFFF"
                android:textSize="18sp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_marginRight="30dp"
                android:layout_centerVertical="true"
                android:text="@string/hp_about" />
        </RelativeLayout>

    </LinearLayout>

</LinearLayout>

运行效果:

展开阅读全文

没有更多推荐了,返回首页