自己动手敲出来的代码,很是不易,留备后用:
package com.view;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.view.View.OnTouchListener;
/**
* Created by maybe on 2016/6/7.
*/
public class ZoomImageView extends ImageView implements ViewTreeObserver.OnGlobalLayoutListener,
ScaleGestureDetector.OnScaleGestureListener, View.OnTouchListener {
private boolean mOnce;
private float mInitScale;
private float mMidScale;
private float mMaxScale;
private Matrix mScaleMatrix;
private ScaleGestureDetector mScaleGestureDetector;
//--------------------------自由移动
private int mLastPointerCount;
private float mLastX;
private float mLastY;
private int mTouchSlop;
private boolean isCanDrag;
private RectF matrixRectF;
private boolean isCheckLeftAndRight;
private boolean isCheckTopAndBottom;
//--------------------------双击放大与缩小
private GestureDetector mGestureDetector;
public ZoomImageView(Context context) {
this(context,null);
}
public ZoomImageView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public ZoomImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mScaleMatrix = new Matrix();
setScaleType(ScaleType.MATRIX);
mScaleGestureDetector = new ScaleGestureDetector(context,this);
setOnTouchListener(this);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mGestureDetector = new GestureDetector(context,
new GestureDetector.SimpleOnGestureListener(){
@Override
public boolean onDoubleTap(MotionEvent e) {
float x = e.getX();
float y = e.getY();
if(getScale() < mMidScale)
{
// mScaleMatrix.postScale(mMidScale/getScale(),mMidScale/getScale(),x,y);
// setImageMatrix(mScaleMatrix);
postDelayed(new AutoScaleRunnable(mMidScale,x,y),16);
boolean isAutoScale = true;
}
else
{
// mScaleMatrix.postScale(mInitScale/getScale(),mInitScale/getScale(),x,y);
// setImageMatrix(mScaleMatrix);
postDelayed(new AutoScaleRunnable(mInitScale,x,y),16);
boolean isAutoScale = true;
}
return true;
}
});
}
private class AutoScaleRunnable implements Runnable
{
private float mTargetScale;
private float x;
private float y;
private final float BIGGER = 1.07f;
private final float SMALL = 0.93f;
private float tmpScale;
public AutoScaleRunnable(float mTargetScale,float x,float y)
{
this.mTargetScale = mTargetScale;
this.x = x;
this.y = y;
if(getScale() < mTargetScale)
{
tmpScale = BIGGER;
}
if(getScale() > mTargetScale)
{
tmpScale = SMALL;
}
}
@Override
public void run() {
mScaleMatrix.postScale(tmpScale,tmpScale,x,y);
checkBorderAndCenterWhenScale();
setImageMatrix(mScaleMatrix);
float currentScalel = getScale();
if((tmpScale > 1.0f && currentScalel < mTargetScale)||
(tmpScale < 1.0f && currentScalel > mTargetScale))
{
postDelayed(this,16);
}
else
{
float Scale = mTargetScale/currentScalel;
mScaleMatrix.postScale(Scale,Scale,x,y);
checkBorderAndCenterWhenScale();
setImageMatrix(mScaleMatrix);
}
}
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
getViewTreeObserver().addOnGlobalLayoutListener(this);
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
@Override
public void onGlobalLayout() {
if(!mOnce)
{
int width = getWidth();
int height = getHeight();
Drawable d = getDrawable();
if(d == null)
return;
int dw = d.getIntrinsicWidth();
int dh = d.getIntrinsicHeight();
float scale = 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)||(dw < width && dh < height))
{
scale = Math.min(width * 1.0f/dw,height*1.0f/dw);
}
mInitScale = scale;
mMidScale = mInitScale *2;
mMaxScale = mInitScale *4;
int dx = getWidth()/2 - dw/2;
int dy = getHeight()/2 - dh/2;
mScaleMatrix.postTranslate(dx,dy);//移动到中心位置
mScaleMatrix.postScale(mInitScale,mInitScale,
mScaleGestureDetector.getFocusX(),mScaleGestureDetector.getFocusY());
checkBorderAndCenterWhenScale();
setImageMatrix(mScaleMatrix); //完成平移缩放
mOnce = true;
}
}
private RectF getMatrixRectf()//获得缩放后的宽高及个点坐标
{
Matrix matrix = mScaleMatrix;
RectF rectf = new RectF();
Drawable d = getDrawable();
if(d != null)
{
rectf.set(0,0,d.getIntrinsicWidth(),d.getIntrinsicHeight());
matrix.mapRect(rectf);
}
return rectf;
}
private void checkBorderAndCenterWhenScale() {
RectF rect = getMatrixRectf();
float deltaX = 0;
float deltaY = 0;
int width = getWidth();
int height = 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/2f - rect.right + rect.width()/2f;
}
if(rect.height() < height)
{
deltaY = height/2f - rect.bottom + rect.height()/2f;
}
mScaleMatrix.postTranslate(deltaX,deltaY);
}
public float getScale(){
float[] values = new float[9];
mScaleMatrix.getValues(values);
return values[Matrix.MSCALE_X];
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
float scale = getScale();
float scaleFactor = detector.getScaleFactor();
if(getDrawable() == null)
{
return true;
}
if((scale < mMaxScale && scaleFactor > 1.0f)
||(scale > mInitScale && scaleFactor < 1.0f))
{
if(scale * scaleFactor < mInitScale)
{
scaleFactor = mInitScale/scale;
}
if(scale * scaleFactor > mMaxScale)
{
scale = mMaxScale/scale;
}
mScaleMatrix.postScale(scaleFactor,scaleFactor,getWidth()/2,getHeight()/2);
setImageMatrix(mScaleMatrix);
}
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if(mGestureDetector.onTouchEvent(event))
{
return true;
}
mScaleGestureDetector.onTouchEvent(event);
float x = 0;
float y = 0;
int pointerCount = event.getPointerCount();
for(int i = 0; i < pointerCount; i++)
{
x += event.getX(i);
y += event.getY(i);
}
x /= pointerCount;
y /= pointerCount;
if(mLastPointerCount != pointerCount)
{
isCanDrag = false;
mLastX = x;
mLastY = y;
}
mLastPointerCount = pointerCount;
switch (event.getAction())
{
case MotionEvent.ACTION_MOVE:
float dx = x - mLastX;
float dy = y - mLastY;
if(!isCanDrag)
{
isCanDrag = isMoveAction(dx,dy);
}
if(isCanDrag)
{
RectF rectf = getMatrixRectf();
if(getDrawable() != null)
{
isCheckLeftAndRight = isCheckTopAndBottom =true;
if(rectf.width() < getWidth())
{
isCheckLeftAndRight = false;
dx = 0;
}
if(rectf.height() < getHeight())
{
isCheckTopAndBottom = false;
dy = 0;
}
mScaleMatrix.postTranslate(dx,dy);
checkBorderWhenTranslate();
setImageMatrix(mScaleMatrix);
}
}
mLastX = x;
mLastY = y;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mLastPointerCount = 0;
break;
default:
}
return true;
}
private void checkBorderWhenTranslate() {
RectF rectf = getMatrixRectf();
float deltaX = 0;
float deltaY = 0;
int width = getWidth();
int height = getHeight();
if(rectf.top > 0 && isCheckTopAndBottom)
{
deltaY = -rectf.top;
}
if(rectf.bottom < height && isCheckTopAndBottom)
{
deltaY = height - rectf.bottom;
}
if(rectf.left > 0 && isCheckLeftAndRight)
{
deltaX = -rectf.left;
}
if(rectf.right < width && isCheckLeftAndRight)
{
deltaX = width - rectf.right;
}
mScaleMatrix.postTranslate(deltaX,deltaY);
}
private boolean isMoveAction(float dx, float dy) {
return Math.sqrt(dx*dx + dy*dy) > mTouchSlop;
}
}
ZoomImageView.java 文件,实现图片的放大缩小,移动,以及双击放大缩小!
热门评论
收藏学习了不错1。。。。