Android Gallery3D

MainActivity

package org.wp.activity;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.ViewConfiguration;
import android.widget.FrameLayout;
import android.widget.ImageView;

public class MainActivity extends Activity {
	/** 图片资源ID **/
	private Integer[] mImageIds = { R.drawable.image1, R.drawable.image2,
			R.drawable.image3, R.drawable.image4, R.drawable.image5,
			R.drawable.image6 };
	
	private static final int LEFT = 0x10;
	private static final int RIGHT = 0x11;

	/** FreamLayout **/
	private FrameLayout mContainer;
	/** 第一个ImageView **/
	private ImageView myIv1;
	/** 第二个ImageView **/
	private ImageView myIv2;
	/** 底部圆圈 **/
	private PageControlView pageControlView = null;

	/** 抖动动画 **/
	private Animation shake;
	/** 手势识别对象GestureDetector **/
	private GestureDetector gestureDetector = null;

	/** Handler对象 **/
	public Handler iHandler;

	/** 标识是否动画正在执行 **/
	private boolean flag = false;
	/** 定时开始时间 **/
	private long start;
	/** 当前时间 **/
	private long end;

	/** 显示图片的数量 **/
	private final int childCount = 6;
	/** 当前屏幕索引 **/
	private int currentScreenIndex = 0;
	/** ImageView先后顺序 **/
	private int currentIndex = 0;
	private final int iv1Index = 1;
	private final int iv2Index = 2;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		addBtnEvent();
		addMessageHandler();
	}

	private void addBtnEvent() {
		// 抖动动画
		shake = AnimationUtils.loadAnimation(this, R.anim.shake);
		// 手势识别
		gestureDetector = new GestureDetector(new FlingGestureDetector());

		mContainer = (FrameLayout) this.findViewById(R.id.mContainer);
		mContainer.setOnTouchListener(new OnTouchListener() {
			@Override
			public boolean onTouch(View arg0, MotionEvent arg1) {
				// 如果没有动画正在执行
				if (!flag) {
					// 当前时间记录为开始时间
					start = System.currentTimeMillis();
					// 判断用户手势
					gestureDetector.onTouchEvent(arg1);
				}
				return false;
			}
		});

		myIv1 = (ImageView) this.findViewById(R.id.myIv1);
		myIv2 = (ImageView) this.findViewById(R.id.myIv2);
		// 初始化显示图片
		myIv2.setImageResource(mImageIds[0]);
		// 初始化当前图片所以为0
		currentScreenIndex = 0;
		// 当前先后索引为iv2Index
		currentIndex = iv2Index;

		pageControlView = (PageControlView) this.findViewById(R.id.myPageControlView);
		/** 设置圆圈的数量 **/
		pageControlView.setCount(childCount);
		/** 初始化圆圈 **/
		pageControlView.generatePageControl(0);

		// 启动监听线程
		new OnFlingListener().start();
	}

	private void addMessageHandler() {
		iHandler = new Handler() {
			public void handleMessage(android.os.Message msg) {
				switch (msg.what) {
				case LEFT:
					scrollToScreen(currentScreenIndex - 1, 90.0f);
					break;
				case RIGHT:
					scrollToScreen(currentScreenIndex + 1, -90.0f);
					break;
				}
			}
		};
	}

	/** 手势识别 **/
	private class FlingGestureDetector extends GestureDetector.SimpleOnGestureListener {
		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY) {
			// 判断是否达到最小轻松速度,取绝对值的
			if (Math.abs(velocityX) > ViewConfiguration.get(MainActivity.this)
					.getScaledMinimumFlingVelocity()) {
				if (velocityX > 0 && currentScreenIndex > 0) {
					// 上一张图片
					scrollToScreen(currentScreenIndex - 1, 90.0f);
				} else if (velocityX < 0 && currentScreenIndex < childCount - 1) {
					// 下一张图片
					scrollToScreen(currentScreenIndex + 1, -90.0f);
				} else {
					// 如果没有,抖动
					mContainer.startAnimation(shake);
				}
			}
			return false;
		}
	}

	/** 切换到指定屏 **/
	public void scrollToScreen(int whichScreen, float degrees) {
		// 更新当前屏幕索引
		currentScreenIndex = whichScreen;
		// 重绘底部圆圈
		pageControlView.callback(currentScreenIndex);
		if (currentIndex == iv1Index) {
			// 如果myIv1在前
			currentIndex = iv2Index;
			// 设置myIv2图片资源
			myIv2.setImageResource(mImageIds[whichScreen]);
			// 旋转myIv1
			applyRotation(myIv1, 0, degrees);
			// 旋转myIv2
			applyRotation(myIv2, -degrees, 0);
		} else if (currentIndex == iv2Index) {
			// 如果myIv2在前
			currentIndex = iv1Index;
			// 设置myIv1图片资源
			myIv1.setImageResource(mImageIds[whichScreen]);
			// 旋转myIv2
			applyRotation(myIv2, 0, degrees);
			// 旋转myIv1
			applyRotation(myIv1, -degrees, 0);
		}
	}

	/** 实现旋转 **/
	private void applyRotation(ImageView iv, float start, float end) {
		final float centerX = mContainer.getWidth() / 2.0f;
		final float centerY = mContainer.getHeight() / 2.0f;

		final Rotate3dAnimation rotation = new Rotate3dAnimation(start, end,
				centerX, centerY);
		rotation.setDuration(500);
		rotation.setFillAfter(true);
		// 监听第二个动画
		if (start == 90.0f || start == -90.0f)
			rotation.setAnimationListener(new DisplayNextView());

		iv.startAnimation(rotation);
	}

	/** 动画监听器 **/
	private final class DisplayNextView implements Animation.AnimationListener {
		@Override
		public void onAnimationEnd(Animation arg0) {
			flag = false;
		}

		@Override
		public void onAnimationRepeat(Animation arg0) {

		}

		@Override
		public void onAnimationStart(Animation arg0) {
			flag = true;
		}
	}

	/** 定时旋转线程 **/
	private final class OnFlingListener extends Thread {
		private boolean isRunning = true;

		@Override
		public void run() {
			start = System.currentTimeMillis();
			end = start;
			// 标识是否到达最后
			boolean bol = false;
			while (isRunning) {
				end = System.currentTimeMillis();
				// 如果没有动画正在进行且用户空闲操作时间超过3秒
				if (!flag && (end - start > 3000)) {
					if (!bol) {
						if (currentScreenIndex < childCount - 1) {
							start = end;
							iHandler.sendEmptyMessage(RIGHT);
						} else if (currentScreenIndex == childCount - 1) {
							bol = true;
						}
					} else {
						if (currentScreenIndex > 0) {
							start = end;
							iHandler.sendEmptyMessage(LEFT);
						} else if (currentScreenIndex == 0) {
							bol = false;
						}
					}
				}
			}
		}

		// 关闭监听线程
		@SuppressWarnings("unused")
		public void shutDown() {
			isRunning = false;
		}
	}
	
	/** 底部圆圈显示回调接口 **/
	interface ScrollToScreenCallback {
		public void callback(int currentIndex);
	}
}

PageControlView

package org.wp.activity;

import org.wp.activity.MainActivity.ScrollToScreenCallback;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class PageControlView extends LinearLayout implements ScrollToScreenCallback {
	/** Context对象 **/
	private Context context;
	/** 圆圈的数量 **/
	private int count;

	public PageControlView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context = context;
	}

	@Override
	public void callback(int currentIndex) {
		generatePageControl(currentIndex);
	}

	public void generatePageControl(int currentIndex) {
		this.removeAllViews();

		for (int i = 0; i < this.count; i++) {
			ImageView iv = new ImageView(context);
			if (currentIndex == i) {
				iv.setImageResource(R.drawable.page_indicator_focused);
			} else {
				iv.setImageResource(R.drawable.page_indicator);
			}
			this.addView(iv);
		}
	}

	/** 设置圆圈数量 **/
	public void setCount(int count) {
		this.count = count;
	}
}

Rotate3dAnimation

package org.wp.activity;

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

public class Rotate3dAnimation extends Animation {
	/** 开始旋转的角度 **/
	private final float mFromDegrees;
	/** 旋转结束的角度 **/
	private final float mToDegrees;
	/** 图片中心X坐标 **/
	private final float mCenterX;
	/** 图片中心Y坐标 **/
	private final float mCenterY;
	/** 视角 **/
	private Camera mCamera;

	public Rotate3dAnimation(float fromDegrees, float toDegrees, float centerX, float centerY) {
		this.mFromDegrees = fromDegrees;
		this.mToDegrees = toDegrees;
		this.mCenterX = centerX;
		this.mCenterY = centerY;
	}

	@Override
	public void initialize(int width, int height, int parentWidth, int parentHeight) {
		super.initialize(width, height, parentWidth, parentHeight);
		mCamera = new Camera();
	}

	@Override
	protected void applyTransformation(float interpolatedTime, Transformation t) {
		final float fromDegrees = mFromDegrees;
		// 生成中间角度
		float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);
		
		final float centerX = mCenterX;
		final float centerY = mCenterY;
		final Camera camera = mCamera;
		
		final Matrix matrix = t.getMatrix();

		if (degrees >= 76.0f) {
			// 旋转角度大于76度保持90度
			degrees = 90.0f;
			camera.save();
			camera.rotateY(degrees);
			camera.getMatrix(matrix);
			camera.restore();
		} else if (degrees <= -76.0f) {
			// 旋转角度小于-76度保持-90度
			degrees = -90.0f;
			camera.save();
			camera.rotateY(degrees);
			camera.getMatrix(matrix);
			camera.restore();
		} else {
			camera.save();
			// 缩小
			camera.translate(0, 0, centerX);
			camera.rotateY(degrees);
			// 旋转产生偏移效果
			camera.translate(0, 0, -centerX);
			camera.getMatrix(matrix);
			camera.restore();
		}

		matrix.preTranslate(-centerX, -centerY);
		matrix.postTranslate(centerX, centerY);
	}
}

anim

shake.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- 
	fromXDelta x轴开始位置
	toXDelta x轴结束位置 
	duration 执行时间 
	interpolator 动画变化率
 -->
<translate xmlns:android="http://schemas.android.com/apk/res/android"
	android:fromXDelta="0" android:toXDelta="10" android:duration="850" android:interpolator="@anim/cycle_5" />

cycle_5.xml

<?xml version="1.0" encoding="utf-8"?>
<cycleInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:cycles="5" />

相关推荐