Skip to content

Instantly share code, notes, and snippets.

@feng88724
Created April 23, 2013 02:49
Show Gist options
  • Save feng88724/5440449 to your computer and use it in GitHub Desktop.
Save feng88724/5440449 to your computer and use it in GitHub Desktop.
Simple TouchImageView for Android. drag freely.
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
/**
* 大图浏览
* 实现了多点触碰、拖动、两指缩放、双击缩放
* (需手动指定容器大小setScreenWidth/setScreenHeight,否则仅适合全屏使用)
* @author Robot
*/
public class TouchView extends ImageView {
static final int NONE = 0;
static final int DRAG = 1; //拖动中
static final int ZOOM = 2; //缩放中
static final int BIGGER = 3; //放大ing
static final int SMALLER = 4; //缩小ing
private int mode = NONE; //当前的事件
private float beforeLenght; //两触点距离
private float afterLenght; //两触点距离
private float scale = 0.04f; //缩放的比例 X Y方向都是这个值 越大缩放的越快,但越小越精细
//最大放大倍数(默认原图2倍)
private float MAX_SCALE = 2f;
//最小缩小倍数(默认原图1/2倍)
private float MIN_SCALE = 2f;
//显示区域大小
private int screenW;
private int screenH;
//原始图片大小
private int WIDTH_IMAGE_ORIGINAL;
private int HEIGHT_IMAGE_ORIGINAL;
private int minWidth;
private int minHeight;
/*处理拖动 变量 */
private int start_x;
private int start_y;
private int stop_x ;
private int stop_y ;
private TranslateAnimation trans; //处理超出边界的动画
private long mTimeOfFirstPointerDown;//前一次按下时间
private long mTimeOfLastClick;//后一次离开时间
public TouchView(Context context) {
super(context);
init(context);
}
/**
* @param context
* @param attrs
*/
public TouchView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
this.setPadding(0, 0, 0, 0);
this.setScaleType(ScaleType.CENTER_INSIDE);
this.setAdjustViewBounds(true);
this.setBackgroundColor(Color.alpha(122));
screenW = ((Activity)context).getWindowManager().getDefaultDisplay().getWidth();
screenH = ((Activity)context).getWindowManager().getDefaultDisplay().getHeight();
}
/**
* 两点间的距离
*/
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float)Math.sqrt(x * x + y * y);
}
/**
* 处理触碰
*/
@Override
public boolean onTouchEvent(MotionEvent event)
{
Log.d("TouchView", "Mode Type: " + mode);
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mTimeOfFirstPointerDown = System.currentTimeMillis();
mode = DRAG;
stop_x = (int) event.getRawX();
stop_y = (int) event.getRawY();
start_x = (int) event.getX();
start_y = stop_y - this.getTop();
if(event.getPointerCount()==2)
beforeLenght = spacing(event);
break;
case MotionEvent.ACTION_POINTER_DOWN:
mTimeOfFirstPointerDown = mTimeOfLastClick = 0;
if (spacing(event) > 10f) {
mode = ZOOM;
beforeLenght = spacing(event);
}
break;
case MotionEvent.ACTION_UP:
if (System.currentTimeMillis() - mTimeOfFirstPointerDown <= 300){
if (mTimeOfLastClick > 0 && System.currentTimeMillis() - mTimeOfLastClick <= 300){//双击
//双击时, 让图片大小超过屏幕
int maxWidth = WIDTH_IMAGE_ORIGINAL;
int maxHeight = HEIGHT_IMAGE_ORIGINAL;
if(getWidth() <= maxWidth && getHeight() <= maxHeight) {
//图片小于屏幕, 自动放大
while(getWidth() < maxWidth || getHeight() < maxHeight) {
setScale(scale, BIGGER);
}
} else {
//图片大于屏幕, 自动缩小
while(getWidth() > screenW || getHeight() > screenH) {
setScale(scale, SMALLER);
}
}
mTimeOfLastClick = 0;
} else {//单击
mTimeOfLastClick = System.currentTimeMillis();
this.performClick();
}
}
/*判断是否超出范围 并处理*/
int disX = 0;
int disY = 0;
//图片宽高
if(getHeight() <= screenH) {
if(this.getTop() < 0) {
int dis = getTop();
this.layout(this.getLeft(), 0, this.getRight(), 0 + this.getHeight());
disY = dis - getTop();
} else if(this.getBottom() > screenH) {
disY = getBottom() - screenH;
this.layout(this.getLeft(), screenH-getHeight(), this.getRight(), screenH);
}
} else {//图片高度超出显示范围
if(this.getTop() < 0 && this.getBottom() < screenH) {
disY = getHeight()- screenH+getTop();
this.layout(this.getLeft(), screenH-getHeight(), this.getRight(), screenH);
} else if(this.getTop() > 0 && this.getBottom() > screenH) {
int dis = getTop();
this.layout(this.getLeft(), 0, this.getRight(), 0 + this.getHeight());
disY = dis - getTop();
}
}
if(getWidth() <= screenW) {
if(this.getLeft() < 0) {
disX = getLeft();
this.layout(0, this.getTop(), 0+getWidth(), this.getBottom());
} else if(this.getRight() > screenW) {
disX = getRight() - screenW;
this.layout(screenW-getWidth(), this.getTop(), screenW, this.getBottom());
}
} else {//图片宽度超出显示范围
Log.d("TouchView", "Left: " + getLeft() + " Right: " + getRight());
if(this.getLeft() > 0 && this.getRight() > screenW) {
disX = getLeft();
this.layout(0, this.getTop(), 0+getWidth(), this.getBottom());
} else if(this.getLeft() < 0 && this.getRight() < screenW) {
disX = getRight() - screenW;
this.layout(screenW-getWidth(), this.getTop(), screenW, this.getBottom());
}
}
if(disX!=0 || disY!=0) {
trans = new TranslateAnimation(disX, 0, disY, 0);
trans.setDuration(300);
this.startAnimation(trans);
}
mode = NONE;
break;
case MotionEvent.ACTION_POINTER_UP:
//图片缩的比屏幕小,自动放大
if(getWidth() < minWidth && getHeight() < minHeight) { //原图大, 不允许小于屏幕; 原图小; 不允许小于原图
while(getWidth() < minWidth && getHeight() < minHeight) {
setScale(scale, BIGGER);
}
} else if(getWidth() > WIDTH_IMAGE_ORIGINAL && getHeight() > HEIGHT_IMAGE_ORIGINAL) {//超出原图大小
while(getWidth() > WIDTH_IMAGE_ORIGINAL && getHeight() > HEIGHT_IMAGE_ORIGINAL) {
setScale(scale, SMALLER);
}
}
mode = NONE;
break;
case MotionEvent.ACTION_MOVE:
/*处理拖动*/
if (mode == DRAG) {
if(Math.abs(stop_x-start_x-getLeft())<88 && Math.abs(stop_y - start_y-getTop())<85)
{
this.setPosition(stop_x - start_x, stop_y - start_y, stop_x + this.getWidth() - start_x, stop_y - start_y + this.getHeight());
stop_x = (int) event.getRawX();
stop_y = (int) event.getRawY();
}
}
/*处理缩放*/
else if (mode == ZOOM) {
if(spacing(event) > 10f) {
afterLenght = spacing(event);
float gapLenght = afterLenght - beforeLenght;
if(gapLenght == 0) {
break;
} else if(Math.abs(gapLenght) > 5f) {//双指放大/缩小
if(gapLenght > 0) {//放大
if(getWidth() < WIDTH_IMAGE_ORIGINAL*MAX_SCALE && getHeight() < HEIGHT_IMAGE_ORIGINAL*MAX_SCALE) {//不允许超出原图大小, 防止无限放大
this.setScale(scale,BIGGER);
}
} else {//缩小
if(getWidth() > minWidth/MIN_SCALE || getHeight() > minHeight/MIN_SCALE) {//不允许小于显示区域的一半,防止无限缩小
this.setScale(scale,SMALLER);
}
}
beforeLenght = afterLenght;
}
}
}
break;
}
return true;
}
/**
* 实现处理缩放
*/
private void setScale(float temp, int flag) {
if (flag == BIGGER) {
this.setFrame(this.getLeft() - (int) (temp * this.getWidth()),
this.getTop() - (int) (temp * this.getHeight()),
this.getRight() + (int) (temp * this.getWidth()),
this.getBottom() + (int) (temp * this.getHeight()));
} else if (flag == SMALLER) {
this.setFrame(this.getLeft() + (int) (temp * this.getWidth()),
this.getTop() + (int) (temp * this.getHeight()),
this.getRight() - (int) (temp * this.getWidth()),
this.getBottom() - (int) (temp * this.getHeight()));
}
}
/**
* 实现处理拖动
*/
private void setPosition(int left,int top,int right,int bottom) {
this.layout(left,top,right,bottom);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if(this.getDrawable() != null) {
WIDTH_IMAGE_ORIGINAL = this.getDrawable().getIntrinsicWidth();
HEIGHT_IMAGE_ORIGINAL = this.getDrawable().getIntrinsicHeight();
}
minWidth = Math.min(screenW, WIDTH_IMAGE_ORIGINAL);
minHeight = Math.min(screenH, HEIGHT_IMAGE_ORIGINAL);
}
/**
* @return the screenW
*/
public int getScreenWidth() {
return screenW;
}
/**
* @param screenW the screenW to set
*/
public void setScreenWidth(int screenW) {
this.screenW = screenW;
}
/**
* @return the screenH
*/
public int getScreenHeight() {
return screenH;
}
/**
* @param screenH the screenH to set
*/
public void setScreenHeight(int screenH) {
this.screenH = screenH;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment