您的位置:首页 > 移动开发 > Android开发

采用Matrix实现图片查看

2016-01-18 16:50 459 查看
 本文是采用重写ImgView实现图片放大,缩放,移动,裁剪,

    package com.example.app.view;

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
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;

/**
* Created by User on 2015/12/13.
*/
public class ZoomImageView extends ImageView implements ViewTreeObserver.OnGlobalLayoutListener,
ScaleGestureDetector.OnScaleGestureListener, View.OnTouchListener {

private boolean mOnce = false;

/**
* 初始化时缩放的值
*/
private float mInitScale;

//private float minInitScale;
/**
* 双击放大值到达的值
*/
private float mMidScale;
/**
* 放大的大值到达的值
*/
private float mMaxScale;

/**
* 捕获用户多指触控是缩放的比例
*/
private ScaleGestureDetector scaleGestureDetector;

private Matrix mScaleMatrix;

//----------自由移动

/**
* 记录上一次多点触控的数量
*/
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;
private boolean isAutoScale;

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();
super.setScaleType(ScaleType.MATRIX);
scaleGestureDetector = new ScaleGestureDetector(context, this);
mGestureDetector = new GestureDetector(context, new

GestureDetector.SimpleOnGestureListener() {

@Override
public boolean onDoubleTap(MotionEvent e) {

if (isAutoScale) {
return true;
}

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);
isAutoScale = true;
} else {

// mScaleMatrix.postScale(mInitScale / getScale(), mInitScale / getScale(), x,

y);
// setImageMatrix(mScaleMatrix);
postDelayed(new AutoScaleRunnable(mInitScale, x, y), 16);
isAutoScale = true;
}

return true;
}
});
this.setOnTouchListener(this);
//判断是否是移动
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}

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);
ckecheBorderAndCenterWhenScale();
setImageMatrix(mScaleMatrix);

float currentScale = getScale();

if ((tmpScale > 1.0f && currentScale < mTargetScale) || (tmpScale < 1.0f &&

currentScale > mTargetScale)) {

postDelayed(this, 16);
} else {
//设置为目标值
float scale = mTargetScale / currentScale;
mScaleMatrix.postScale(scale, scale, x, y);
ckecheBorderAndCenterWhenScale();
setImageMatrix(mScaleMatrix);
isAutoScale = false;
}
}
}

@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
//添加
getViewTreeObserver().addOnGlobalLayoutListener(this);

}

@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
//删除
getViewTreeObserver().removeGlobalOnLayoutListener(this);
}

/**
* 获取ImageView加载完成的图片
*/
@Override
public void onGlobalLayout() {
if (!mOnce) {

//得到控件的宽和高
int width = getWidth();
int height = getHeight();

//得到我们的图片,以及宽和高
Drawable drawable = getDrawable();
if (drawable == null) {
return;
}
int drawableWidth = drawable.getIntrinsicWidth();
int drawableHeight = drawable.getIntrinsicHeight();

float scale = 1.0f;

float minScale = 1.0f;

/**
* 如果图片的宽度大于控件宽度,但是高度小于控件宽度,我们将其放大、
* */
if (drawableWidth > width && drawableHeight < height) {

scale = width * 1.0f / drawableWidth;
}
/**
* 如果图片的高度于控件高度,但是宽度小于控件宽度,我们将其缩小、
* */
if (drawableHeight > height && drawableWidth < width) {

scale = height * 1.0f / drawableHeight;
}

/**
* 如果图片的宽高都大于控件,我们将其缩小,。
* */
if (drawableWidth > width && drawableHeight > height) {

scale = Math.min(width * 1.0f / drawableWidth, height * 1.0f / drawableHeight);
}

/**
* 如果图片的宽高都小于控件,我们将其放大。
* */
if (drawableWidth < width && drawableHeight < height) {

scale = Math.min(width * 1.0f / drawableWidth, height * 1.0f / drawableHeight);
}

/**
* 得到了初始化时缩放的比例
* */
mInitScale = scale;
mMaxScale = mInitScale * 4;
mMidScale = mInitScale * 2;
// minInitScale = minScale;
mOnce = true;

/**
* 将图片移动至控件的中心
* */
int dx = getWidth() / 2 - drawableWidth / 2;
int dy = getHeight() / 2 - drawableHeight / 2;

mScaleMatrix.postTranslate(dx, dy);
mScaleMatrix.postScale(mInitScale, mInitScale, width / 2, height / 2);
setImageMatrix(mScaleMatrix);

}

}

//缩放的区间:initScale,MaxScale

//获取图片当前的缩放值
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();

Log.d("scaleFactor", ":" + scaleFactor);
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) {
scaleFactor = mMaxScale / scale;
}

mScaleMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(),

detector.getFocusY());
ckecheBorderAndCenterWhenScale();
setImageMatrix(mScaleMatrix);
}

return true;
}

/**
* 获得图片放大缩小以后的宽和高,以及l,r,t,b
*/
private RectF getMatrixRectF() {
Matrix rMatrix = mScaleMatrix;
RectF rectF = new RectF();
Drawable d = getDrawable();

if (d != null) {
rectF.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
rMatrix.mapRect(rectF);
}
return rectF;
}

/**
* 再缩放的时候进行边界控制已经我们的位置的控制
*/
private void ckecheBorderAndCenterWhenScale() {

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;

b2ce
}
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();
}

mScaleMatrix.postTranslate(deltaX, deltaY);
}

@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;
}
scaleGestureDetector.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) {
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;
}

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);
}

/**
* 判断是否是Move
*/
private boolean isMoveAction(float dx, float dy) {

return Math.sqrt(dx * dx + dy * dy) > mTouchS
}

/**
* 剪切图片,返回剪切后的bitmap对象 圆形用
*
* @return
*/
public Bitmap clip() {
Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
int yStartPoint = DensityUtils.dp2px(getContext(), (float) 135.333);
int xStartPoint = DensityUtils.dp2px(getContext(), (float) 62);
int circleRadius = DensityUtils.dp2px(getContext(), (float) 236);
draw(canvas);
return Bitmap.createBitmap(bitmap, xStartPoint,
yStartPoint, circleRadius,
circleRadius);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 图片 matrix