Android 实现,图片双指缩放,单指移动。通过自定义ImageView控件实现。
ZoomDragImageView.java代码如下:
public class SwZoomDragImageView extends ImageView implements View.OnTouchListener{
private static final String TAG = SwZoomDragImageView.class.getSimpleName();
private boolean support_touch = true;//支持触摸事件
private int mode = 0;// 初始状态
private static final int MODE_DRAG = 1;//平移
private static final int MODE_ZOOM = 2;//缩放
private static final float MAX_SCALE = 4f, MIN_SCALE = 1f;//最大放大倍数,最小放大倍数
float total_scale = MIN_SCALE , current_scale;//total_scale缩放范围2-1,当小于1回弹到1;当大于2回弹到2
private Matrix matrixNow = new Matrix();
private Matrix matrixBefore = new Matrix();
private Matrix mInitializationMatrix = new Matrix();//初始缩放值
private PointF actionDownPoint = new PointF();//点击点
private PointF dragPoint = new PointF();//平移点
private PointF startPoint = new PointF();//滑动点
private PointF mInitializationScalePoint = new PointF();//初始缩放点
private PointF mCurrentScalePoint = new PointF(0, 0);//当前缩放点
private float startDis;//滑动开始距离
/** 两个手指的中间点 */
private PointF midPoint = new PointF(0,0);
public SwZoomDragImageView(Context context) {
this(context, null);
}
public SwZoomDragImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SwZoomDragImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initData();
}
private void initData() {
if (support_touch) {
setOnTouchListener(this);
}
this.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
SwZoomDragImageView.this.getViewTreeObserver().removeOnGlobalLayoutListener(this);
int[] viewLocation = new int[2];
SwZoomDragImageView.this.getLocationInWindow(viewLocation);
int viewX = viewLocation[0]; // x 坐标;有bug,在viewpage中。
int viewY = viewLocation[1]; // y 坐标
mInitializationScalePoint.set( SwZoomDragImageView.this.getWidth() / 2, viewY + SwZoomDragImageView.this.getHeight() / 2);//初始化缩放位置
Log.i("yangxun", "控件 宽:" + mInitializationScalePoint.x + "高:" + mInitializationScalePoint.y);
}
});
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);//清空画布
if (matrixNow != null) {
canvas.concat(matrixNow);
// canvas.setMatrix(matrixNow);//显示有问题
}
super.onDraw(canvas);
} @Override
public void setImageMatrix(Matrix matrix) {
matrixNow.set(matrix);
invalidate();
}
public void resetImageMatrix() {
this.matrixNow.set(mInitializationMatrix);
invalidate();
}
//最小重置数值
private void resetToMinStatus(){
mCurrentScalePoint.set(0, 0);
total_scale = MIN_SCALE;
}
//最大重置数值
private void resetToMaxStatus(){
total_scale = MAX_SCALE;
}
public float getInitializationBitmapHeight(){
return getHeight()*total_scale;
}
public float getInitializationBitmapWidth(){
return getWidth()*total_scale;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (total_scale != 1) {
getParent().requestDisallowInterceptTouchEvent(true);//触摸事件请求拦截
}
/** 通过与运算保留最后八位 MotionEvent.ACTION_MASK = 255 */
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN://单指触摸
mode = MODE_DRAG;
matrixBefore.set(getImageMatrix());
matrixNow.set(getImageMatrix());
dragPoint.set(event.getX(), event.getY());
actionDownPoint.set(event.getX(), event.getY());
break;
case MotionEvent.ACTION_POINTER_DOWN://双指触摸
getParent().requestDisallowInterceptTouchEvent(true);//触摸事件请求拦截
mode = MODE_ZOOM;
startPoint.set(event.getX(), event.getY());
startDis = distance(event);
/** 计算两个手指间的中间点 */
if (startDis > 10f) {
//记录当前ImageView的缩放倍数
matrixBefore.set(getImageMatrix());
matrixNow.set(getImageMatrix());
}
break;
case MotionEvent.ACTION_MOVE:
if (mode == MODE_DRAG && total_scale > 1) {
float dx = event.getX() - dragPoint.x;
float dy = event.getY() - dragPoint.y;
dragPoint.set(event.getX(), event.getY());
imgTransport(dx, dy);
} else if (mode == MODE_ZOOM) {//缩放
float endDis = distance(event);
midPoint = mid(event);
if (endDis > 10f) {
current_scale = endDis / startDis;//缩放倍数
total_scale *= current_scale;
matrixNow.postScale(current_scale, current_scale, midPoint.x, midPoint.y);
invalidate();
}
startDis = endDis;
}
break;
case MotionEvent.ACTION_UP:
getParent().requestDisallowInterceptTouchEvent(false);//触摸事件请求取消拦截
mode = 0;
if(mode == MODE_DRAG)
checkClick(event.getX(),event.getY(), actionDownPoint.x, actionDownPoint.y);
break;
case MotionEvent.ACTION_POINTER_UP:
checkZoomValid();
mode = 0;
break;
}
return true;
}
/**
* 平移图片
* @param x
* @param y
*/
public void imgTransport(float x,float y){
mCurrentScalePoint.set(mCurrentScalePoint.x + x, mCurrentScalePoint.y + y);
if (mCurrentScalePoint.x >= ((total_scale - 1) * getWidth()) / 2) {
mCurrentScalePoint.x = ((total_scale - 1) * getWidth()) / 2;
x = 0;
} else {
if (mCurrentScalePoint.x <= -((total_scale - 1) * getWidth()) / 2) {
mCurrentScalePoint.x = -((total_scale - 1) * getWidth()) / 2;
x = 0;
}
}
if (mCurrentScalePoint.y >= ((total_scale - 1) * getHeight()) / 2) {
mCurrentScalePoint.y = ((total_scale - 1) * getHeight()) / 2;
y = 0;
} else {
if (mCurrentScalePoint.y <= -((total_scale - 1) * getHeight()) / 2) {
mCurrentScalePoint.y = -((total_scale - 1) * getHeight()) / 2;
y = 0;
}
}
Log.i(TAG, "mCurrentScalePoint.x:" + mCurrentScalePoint.x + " x:" + x);
matrixNow.postTranslate(x, y);
invalidate();
}
private boolean checkZoomValid() {
if(mode == MODE_ZOOM){
if(total_scale>MAX_SCALE){
resetToMaxStatus();
matrixNow.set(mInitializationMatrix);
matrixNow.postScale(MAX_SCALE, MAX_SCALE, mInitializationScalePoint.x, mInitializationScalePoint.y);
matrixNow.postTranslate(mCurrentScalePoint.x, mCurrentScalePoint.y);
invalidate();
return false;
}else if(total_scale
好了,现在直接使用该类,就可以直接对图片进行相应操作。