import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
public class CalleryActivity extends Activity implements OnGestureListener {
private FlingView flingView;//自定义View
private GestureDetector myGesture;//用来注册事件的
public static int deviceScreenWidth;
public static int deviceScreenHeight;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 鑾峰緱鎵嬫満鐨勫甯﹀拰楂樺害鍍忕礌鍗曚綅涓簆x
DisplayMetrics dm = new DisplayMetrics();//创建一个结构体来描述显示图片
getWindowManager().getDefaultDisplay().getMetrics(dm);//获得一个结结构体
deviceScreenWidth = dm.widthPixels;//结构体的绝对像素宽
deviceScreenHeight = dm.heightPixels;//结构体的绝对像素高
Log.i("LOG", "Activity --> deviceScreenWidth = " + deviceScreenWidth + "; deviceScreenHeight = " + deviceScreenHeight);
Bitmap[] bitmaps = {
//从源文件里解析出里面的位图
BitmapFactory.decodeResource(getResources(), R.drawable.img1),
BitmapFactory.decodeResource(getResources(), R.drawable.img2),
BitmapFactory.decodeResource(getResources(), R.drawable.img3),
BitmapFactory.decodeResource(getResources(), R.drawable.img4),
BitmapFactory.decodeResource(getResources(), R.drawable.img5) };
myGesture = new GestureDetector(this);//手势监听器
flingView = new FlingView(this, bitmaps);
setContentView(flingView);//使用flingView作为布局文件
Log.i("LOG", "Layout finished!!!");
}
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
flingView.onFling(0);//当用户松开手后 ,offsetX = 0
break;
}
Log.i("LOG", "TOUCH!!!");
//Detector注册Event事件,如果不注册是不会回调那些相应动作的方法的
return myGesture.onTouchEvent(event);
}
public boolean onDown(MotionEvent e) {
return false;
}
//滑动时触发
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.i("LOG", "velocityX = " + velocityX + "; velocityY = " + velocityY);
flingView.onFling(-1 * (int)velocityX);
// Log.i("LOG","offsetX = "+ offsetX );
return true;
}
//长按是触发
public void onLongPress(MotionEvent e) {
}
//滚动时触发,(按着拖动时,会不断触发此方法,当松开手时,就触发onFling)
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
Log.i("LOG", "distanceX = " + distanceX + "; distanceY = " + distanceY);
flingView.handleScroll(-1 * (int) distanceX);
return true;
}
public void onShowPress(MotionEvent e) {
}
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
}
//
package yy.android.callery;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.Transformation;
public class FlingView extends View {
private Bitmap bitmap;
private Bitmap nBitmap;
private Bitmap fBitmap;
public int offsetX = 0;
public int offsetY = 0;
public int postion = 0;//位图的位置从0开始
private Bitmap[] bitmaps;
public FlingView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FlingView(Context context, Bitmap[] bitmaps) {
super(context);
this.bitmaps = bitmaps;
bitmap = getBitmap(0);//当前图
nBitmap = getBitmap(1);//右一张图
}
@Override//布局完这个方法就会先被调用,重绘时也会对调
public void draw(Canvas canvas) {
Log.i("LOG", "Draw!!!");
Paint paint = new Paint();//画笔
Rect rect = new Rect();//矩形
canvas.drawColor(Color.BLACK);//过度颜色
// 当前位图不为空,这段主要是绘制当前图的,如果滑动的,则只绘制剩下的部分,其余部分黑色
if (bitmap != null) {
int left = offsetX;//初始化状态,X方向的偏移
int top = offsetY;//初始化状态,Y方向的偏移
//注意,如果右边的坐标超过了平幕的宽度,则图片会被拉宽到有一部分是不可见的
int right = offsetX + CalleryActivity.deviceScreenWidth;//位图的右边位置
int bottom = offsetY + CalleryActivity.deviceScreenHeight;//位图底部位置
//设置矩形区域的边界
rect.set(left, top, right, bottom);
//绘制图片出来
canvas.drawBitmap(bitmap, null, rect, paint);
}
//当向左滑动时,这段是绘制相邻图片的,填充上面那段的黑色部分(填右)
if (offsetX < 0) {
//而且右边有位图存在的话
if (nBitmap != null) {
//以下式里的10是两张图片之间的空隙,注意此时X偏移为负数
int left = CalleryActivity.deviceScreenWidth + 15 + offsetX;
int top = 0;
int right = left + CalleryActivity.deviceScreenWidth;
int bottom = CalleryActivity.deviceScreenHeight;
rect.set(left, top, right, bottom);
canvas.drawBitmap(nBitmap, null, rect, paint);
}
//向右滑动时(填左)
} else if (offsetX > 0) {
//而且左边有位图存在
if (fBitmap != null) {
int left = -CalleryActivity.deviceScreenWidth - 15 + offsetX;
int top = 0;
int right = left + CalleryActivity.deviceScreenWidth;
int bottom = CalleryActivity.deviceScreenWidth;
rect.set(left, top, right, bottom);
canvas.drawBitmap(fBitmap, null, rect, paint);
}
}
}
//滚动时触发
public void handleScroll(int deltaX) {
if (deltaX > 0) {//获得当前的偏移量
offsetX -= -deltaX;
} else {
offsetX += deltaX;
}
Log.i("LOG", "HandleScroll!!!");
invalidate();//通知系统重绘
}
/*@Override
protected void onDraw(Canvas canvas) {
Log.i("LOG","onDraw!!!");
super.onDraw(canvas);
}*/
boolean isFling = false; //是否正在滑动
boolean isFlingRight = false; //正在向右滑动
boolean isFlingLeft = false; //正在向左滑动
class MyAnimation extends Animation {//动画类
private int tmpOffsetX;
@Override//初始化动画尺寸,和相对动画父框的尺寸
public void initialize(int width, int height, int parentWidth, int parentHeight) {
tmpOffsetX = offsetX;//临时偏移量
super.initialize(width, height, parentWidth, parentHeight);
setDuration(500);//动画的持续时间
setFillAfter(true);//
setInterpolator(new LinearInterpolator());//设置动画的加速度
}
@Override//在动画播放时不断的调用,直到interpolatedTime等于1.0
protected void applyTransformation(float interpolatedTime, Transformation t) {
Log.i("LOG", "interpolatedTime ==>"+interpolatedTime);
//Log.i("LOG", "interpolatedTime ==>"+interpolatedTime);
if (isFling) {//正在滑动
if (tmpOffsetX > 0) {//正在向右滑动
offsetX = (int) ((CalleryActivity.deviceScreenWidth - tmpOffsetX) * interpolatedTime + tmpOffsetX);
} else {//正在向左滑动
offsetX = (int) ((-CalleryActivity.deviceScreenWidth - tmpOffsetX) * interpolatedTime + tmpOffsetX);
}
} else {//当下一张或前一张,没有图片的时候,返回原图
offsetX = (int) (tmpOffsetX * (1 - interpolatedTime));
}
invalidate();//重绘
}
}
//动画结束后会回调,interpolatedTime==1.0 的时候,为下次的动作做准备
@Override
protected void onAnimationEnd() {
Log.i("LOG", "END!!!");
if (isFlingRight) { //正在向右滑动
nBitmap = bitmap;
bitmap = fBitmap;
fBitmap = null;
postion = postion - 1;
} else if (isFlingLeft) {//向左滑动
fBitmap = bitmap;
bitmap = nBitmap;
nBitmap = null;
postion = postion + 1;
}
isFlingRight = false;
isFlingLeft = false;
isFling = false;
offsetX = 0;
if (fBitmap == null && offsetX == 0) {
if (postion > 0) {//当前位图左边还有图
fBitmap = getBitmap(postion - 1);
}
} else if (nBitmap == null && offsetX == 0) {
if (postion < bitmaps.length - 1) {//当前位图右边还有图
nBitmap = getBitmap(postion + 1);
}
}
clearAnimation(); //清除动画 ,如果不清楚的话动画会一直的播放
}
/** 返回对应CurrentPos的位图*/
public Bitmap getBitmap(int currentPos) {
if (currentPos > bitmaps.length - 1) {
return null;
}
//设置为当前位图,和设置它的偏移量
Bitmap currBitmap = bitmaps[currentPos];
offsetX = 0;
offsetY = 0;
return currBitmap;
}
public void onFling(int paramFloat1) {
Log.i("LOG", "FIleView offsetX = "+offsetX );
if (offsetX > CalleryActivity.deviceScreenWidth / 5) {
//当偏移量大于以上值时,而起当前位图的左边还有图片的话就设置滑动标志位
if (fBitmap != null) {
isFling = true;
isFlingRight = true;
}
} else if (offsetX < -CalleryActivity.deviceScreenWidth / 5) {
if (nBitmap != null) {
isFling = true;
isFlingLeft = true;
}
}//开始播放动画
startAnimation(new MyAnimation());
}
}/另外还要在drawble里加上图片文件(.jpg)
还有一个问题就是,当调用invalidate()通知系统重绘时,为什么触发的是draw方法而不是onDraw方法呢?