android 手势放缩_Android应用中实现手势控制图片缩放

public classZoomImageView extendsAppCompatImageView implementsScaleGestureDetector.OnScaleGestureListener,

View.OnTouchListener, ViewTreeObserver.OnGlobalLayoutListener

{

private static finalString TAG= ZoomImageView.class.getSimpleName();

public static final floatSCALE_MAX= 10.0f;

// 双击时缩放达到的值private floatmMidScale=2.0f;

private floatinitScale= 1.0f;

private final float[] matrixValues= new float[9];

private booleanonce= true;

// 记录上一次多点触控的数量private intmLastPointerCount;

privateScaleGestureDetector mScaleGestureDetector= null;

private finalMatrix mScaleMatrix= newMatrix();

// 是否可移动private booleanisCanDrag;

// 判断private booleanisCheckLeftAndRight;

private booleanisCheckTopAnom;

private floatmLastX;

private floatmLastY;

// 用于中心点的保留private intmTouchSlop;

// -------------------------------------------// 双击放大与缩小// ------------------------------------------privateGestureDetector mGestureDetector;

private booleanisAutoScale;

publicZoomImageView(Context context)

{

this(context, null);

}

publicZoomImageView(Context context, AttributeSet attrs)

{

super(context, attrs);

super.setScaleType(ScaleType.MATRIX);

mScaleGestureDetector= newScaleGestureDetector(context, this);

this.setOnTouchListener(this);

mTouchSlop= ViewConfiguration.get(context).getScaledTouchSlop();

mGestureDetector= newGestureDetector(context,

newGestureDetector.SimpleOnGestureListener() {

@Overridepublic booleanonDoubleTap(MotionEvent e)

{

if(isAutoScale== true)

return true;

floatx = e.getX();

floaty = e.getY();

Log.e("DoubleTap", getScale() + " , "+ initScale);

if(getScale() < mMidScale)

{

ZoomImageView.this.postDelayed(

newAutoScaleRunnable(mMidScale, x, y), 16);

isAutoScale= true;

} else if(getScale() >= mMidScale&& getScale() < SCALE_MAX)

{

ZoomImageView.this.postDelayed(

newAutoScaleRunnable(SCALE_MAX, x, y), 16);

isAutoScale= true;

} else{

ZoomImageView.this.postDelayed(

newAutoScaleRunnable(initScale, x, y), 16);

isAutoScale= true;

}

return true;

}

});

}

@Overridepublic booleanonScale(ScaleGestureDetector detector)

{

floatscale = getScale();

floatscaleFactor = detector.getScaleFactor();

if(getDrawable() == null)

return true;

if((scale < SCALE_MAX&& scaleFactor > 1.0f)

|| (scale > initScale&& scaleFactor < 1.0f))

{

if(scaleFactor * scale < initScale)

{

scaleFactor = initScale/ scale;

}

if(scaleFactor * scale > SCALE_MAX)

{

scaleFactor = SCALE_MAX/ scale;

}

mScaleMatrix.postScale(scaleFactor, scaleFactor,

detector.getFocusX(), detector.getFocusY());

checkBorderAndCenterWhenScale();

setImageMatrix(mScaleMatrix);

}

return true;

}

private voidcheckBorderAndCenterWhenScale()

{

RectF rect = getMatrixRectF();

floatdeltaX = 0;

floatdeltaY = 0;

intwidth = getWidth();

intheight = getHeight();

// 如果宽或高大于屏幕,则控制范围if(rect.width() >= width)

{

if(rect.left> 0)

{

deltaX = -rect.left;

}

if(rect.right< width)

{

deltaX = width - rect.right;

}

}

if(rect.height() >= height)

{

if(rect.top> 0)

{

deltaY = -rect.top;

}

if(rect.bottom< height)

{

deltaY = height - rect.bottom;

}

}

// 如果宽或高小于屏幕,则让其居中if(rect.width() < width)

{

deltaX = width * 0.5f- rect.right+ 0.5f* rect.width();

}

if(rect.height() < height)

{

deltaY = height * 0.5f- rect.bottom+ 0.5f* rect.height();

}

Log.e(TAG, "deltaX = "+ deltaX + " , deltaY = "+ deltaY);

mScaleMatrix.postTranslate(deltaX, deltaY);

}

privateRectF getMatrixRectF()

{

Matrix matrix = mScaleMatrix;

RectF rect = newRectF();

Drawable d = getDrawable();

if(null!= d)

{

rect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());

matrix.mapRect(rect);

}

returnrect;

}

@Overridepublic booleanonScaleBegin(ScaleGestureDetector detector)

{

return true;

}

@Overridepublic voidonScaleEnd(ScaleGestureDetector detector) {

}

public final floatgetScale()

{

mScaleMatrix.getValues(matrixValues);

returnmatrixValues[Matrix.MSCALE_X];

}

@Overrideprotected voidonAttachedToWindow()

{

super.onAttachedToWindow();

getViewTreeObserver().addOnGlobalLayoutListener(this);

}

@SuppressWarnings("deprecation")

@Overrideprotected voidonDetachedFromWindow()

{

super.onDetachedFromWindow();

getViewTreeObserver().removeGlobalOnLayoutListener(this);

}

@Overridepublic voidonGlobalLayout()

{

if(once)

{

Drawable d = getDrawable();

if(d == null)

return;

Log.e(TAG, d.getIntrinsicWidth() + " , "+ d.getIntrinsicHeight());

intwidth = getWidth();

intheight = getHeight();

// 拿到图片的宽和高intdw = d.getIntrinsicWidth();

intdh = d.getIntrinsicHeight();

floatscale = 1.0f;

// 如果图片的宽或者高大于屏幕,则缩放至屏幕的宽或者高if(dw > width && dh <= height)

{

scale = width * 1.0f/ dw;

}

if(dh > height && dw <= width)

{

scale = height * 1.0f/ dh;

}

// 如果宽和高都大于屏幕,则让其按按比例适应屏幕大小if(dw > width && dh > height)

{

scale = Math.min(dw * 1.0f/ width, dh * 1.0f/ height);

}

initScale= scale;

// 图片移动至屏幕中心mScaleMatrix.postTranslate((width - dw) / 2, (height - dh) / 2);

mScaleMatrix.postScale(scale, scale, getWidth() / 2, getHeight() / 2);

setImageMatrix(mScaleMatrix);

once= false;

}

}

// 利用触摸事件,mScaleGestureDetector获得多个焦点坐标,以便实现多点触控@Overridepublic booleanonTouch(View v, MotionEvent event) {

if(mGestureDetector.onTouchEvent(event))

return true;

mScaleGestureDetector.onTouchEvent(event);

floatx = 0, y = 0;

// 拿到触摸点的个数final intpointerCount = event.getPointerCount();

// 得到多个触摸点的x与y均值for(inti = 0; i < pointerCount; i++)

{

x += event.getX(i);

y += event.getY(i);

}

x = x / pointerCount;

y = y / pointerCount;

if(pointerCount != mLastPointerCount)

{

isCanDrag= false;

mLastX= x;

mLastY= y;

}

mLastPointerCount= pointerCount;

switch(event.getAction())

{

caseMotionEvent.ACTION_MOVE:

Log.e(TAG, "ACTION_MOVE");

floatdx = x - mLastX;

floatdy = y - mLastY;

if(!isCanDrag)

{

isCanDrag= isCanDrag(dx, dy);

}

if(isCanDrag)

{

RectF rectF = getMatrixRectF();

if(getDrawable() != null)

{

isCheckLeftAndRight= isCheckTopAnom= true;

// 如果宽度小于屏幕宽度,则禁止左右移动if(rectF.width() < getWidth())

{

dx = 0;

isCheckLeftAndRight= false;

}

// 如果高度小雨屏幕高度,则禁止上下移动if(rectF.height() < getHeight())

{

dy = 0;

isCheckTopAnom= false;

}

mScaleMatrix.postTranslate(dx, dy);

checkMatrixBounds();

setImageMatrix(mScaleMatrix);

}

}

mLastX= x;

mLastY= y;

break;

caseMotionEvent.ACTION_UP:

caseMotionEvent.ACTION_CANCEL:

Log.e(TAG, "ACTION_UP");

mLastPointerCount= 0;

break;

}

return true;

}

private voidcheckMatrixBounds()

{

RectF rect = getMatrixRectF();

floatdeltaX = 0, deltaY = 0;

final floatviewWidth = getWidth();

final floatviewHeight = getHeight();

// 判断移动或缩放后,图片显示是否超出屏幕边界if(rect.top> 0&& isCheckTopAnom)

{

deltaY = -rect.top;

}

if(rect.bottom< viewHeight && isCheckTopAnom)

{

deltaY = viewHeight - rect.bottom;

}

if(rect.left> 0&& isCheckLeftAndRight)

{

deltaX = -rect.left;

}

if(rect.right< viewWidth && isCheckLeftAndRight)

{

deltaX = viewWidth - rect.right;

}

mScaleMatrix.postTranslate(deltaX, deltaY);

}

private booleanisCanDrag(floatdx, floatdy)

{

returnMath.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop;

}

private classAutoScaleRunnable implementsRunnable

{

static final floatBIGGER= 1.07f;

static final floatSMALLER= 0.93f;

private floatmTargetScale;

private floattmpScale;

private floatx;

private floaty;

publicAutoScaleRunnable(floattargetScale, floatx, floaty)

{

this.mTargetScale= targetScale;

this.x= x;

this.y= y;

if(getScale() < mTargetScale)

{

tmpScale= BIGGER;

} else{

tmpScale= SMALLER;

}

}

@Overridepublic voidrun()

{

// 进行缩放mScaleMatrix.postScale(tmpScale, tmpScale, x, y);

checkBorderAndCenterWhenScale();

setImageMatrix(mScaleMatrix);

final floatcurrentScale = getScale();

//如果值在合法范围内,继续缩放if(((tmpScale> 1f) && (currentScale < mTargetScale))

|| ((tmpScale< 1f) && (mTargetScale< currentScale)))

{

ZoomImageView.this.postDelayed(this, 16);

} else//设置为目标的缩放比例{

final floatdeltaScale = mTargetScale/ currentScale;

mScaleMatrix.postScale(deltaScale, deltaScale, x, y);

checkBorderAndCenterWhenScale();

setImageMatrix(mScaleMatrix);

isAutoScale= false;

}

}

}

Activity 代码 解决ontouch事件 与viewpager滑动冲突

public class MainActivity extends Activity

{

private ViewPager mViewPager;

private int[] mImgs = new int[] { R.drawable.tbug, R.drawable.a,

R.drawable.xx };

private ImageView[] mImageViews = new ImageView[mImgs.length];

@Override

protected void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.vp);

mViewPager = (ViewPager) findViewById(R.id.id_viewpager);

mViewPager.setAdapter(new PagerAdapter()

{

@Override

public Object instantiateItem(ViewGroup container, int position)

{

ZoomImageView imageView = new ZoomImageView(

getApplicationContext());

imageView.setImageResource(mImgs[position]);

container.addView(imageView);

mImageViews[position] = imageView;

return imageView;

}

@Override

public void destroyItem(ViewGroup container, int position,

Object object)

{

container.removeView(mImageViews[position]);

}

@Override

public boolean isViewFromObject(View arg0, Object arg1)

{

return arg0 == arg1;

}

@Override

public int getCount()

{

return mImgs.length;

}

});

}

}

switch (event.getAction())

{

case MotionEvent.ACTION_DOWN:

if (rectF.width() > getWidth() || rectF.height() > getHeight())

{

getParent().requestDisallowInterceptTouchEvent(true);

}

break;

case MotionEvent.ACTION_MOVE:

if (rectF.width() > getWidth() || rectF.height() > getHeight())

{

getParent().requestDisallowInterceptTouchEvent(true);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值