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" />