Files
HouseProperty/app/src/main/java/imageselector/view/ClipImageView.java
jinyuer fda8305a13 1
2020-08-14 17:07:43 +08:00

355 lines
12 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package imageselector.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Xfermode;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.WindowManager;
public class ClipImageView extends AppCompatImageView {
private PointF mDownPoint;
private PointF mMiddlePoint;
private Matrix mMatrix;
private Matrix mTempMatrix;
private int mBitmapWidth;
private int mBitmapHeight;
private final int MODE_NONE = 0;
private final int MODE_DRAG = 1;
private final int MODE_ZOOM = 2;
private final int MODE_POINTER_UP = 3;
private int CURR_MODE = MODE_NONE;
private float mLastDistance;
private Paint mFrontGroundPaint = new Paint();
private int mTargetWidth;
private int mTargetHeight;
private Xfermode mXfermode;
private Rect r;
private RectF rf;
private float mCircleCenterX, mCircleCenterY;
private float mCircleX, mCircleY;
private boolean isCutImage;
public ClipImageView(Context context) {
super(context);
setRadius();
}
public ClipImageView(Context context, AttributeSet attrs) {
super(context, attrs);
setRadius();
}
/**
* 设置要剪裁的图片
*
* @param bitmap
*/
public void setBitmapData(Bitmap bitmap) {
if (bitmap == null) {
return;
}
mBitmapHeight = bitmap.getHeight();
mBitmapWidth = bitmap.getWidth();
setImageBitmap(bitmap);
init();
}
private void init() {
mDownPoint = new PointF();
mMiddlePoint = new PointF();
mMatrix = new Matrix();
mTempMatrix = new Matrix();
mFrontGroundPaint.setColor(Color.parseColor("#ac000000"));
mFrontGroundPaint.setAntiAlias(true);
mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);
setScaleType(ScaleType.MATRIX);
post(new Runnable() {
@Override
public void run() {
center();
}
});
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
mCircleCenterX = getWidth() / 2;
mCircleCenterY = getHeight() / 2;
mCircleX = mCircleCenterX - mTargetWidth / 2;
mCircleY = mCircleCenterY - mTargetHeight / 2;
}
private void setRadius() {
int width = getScreenWidth(getContext());
int height = getScreenHeight(getContext());
if (width > height) {
mTargetWidth = height;
mTargetHeight = height;
} else {
mTargetWidth = width;
mTargetHeight = width;
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isCutImage) {
return;
}
if (rf == null || rf.isEmpty()) {
r = new Rect(0, 0, getWidth(), getHeight());
rf = new RectF(r);
}
// 画入前景圆形蒙板层
int sc = canvas.saveLayer(rf, null, Canvas.ALL_SAVE_FLAG);
//画入矩形黑色半透明蒙板层
canvas.drawRect(r, mFrontGroundPaint);
//设置Xfermode目的是为了去除矩形黑色半透明蒙板层和圆形的相交部分
mFrontGroundPaint.setXfermode(mXfermode);
//画入正方形
canvas.drawRect(mCircleCenterX - mTargetWidth / 2, mCircleCenterY - mTargetHeight / 2,
mCircleCenterX + mTargetWidth / 2, mCircleCenterY + mTargetHeight / 2, mFrontGroundPaint);
canvas.restoreToCount(sc);
//清除Xfermode防止影响下次画图
mFrontGroundPaint.setXfermode(null);
}
/**
* 截取Bitmap
*
* @return
*/
public Bitmap clipImage() {
isCutImage = true;
Paint paint = new Paint();
setDrawingCacheEnabled(true);
Bitmap bitmap = getDrawingCache();
Bitmap targetBitmap = Bitmap.createBitmap(mTargetWidth, mTargetHeight,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(targetBitmap);
RectF dst = new RectF(-bitmap.getWidth() / 2 + mTargetWidth / 2, -getHeight()
/ 2 + mTargetHeight / 2, bitmap.getWidth() / 2
+ mTargetWidth / 2, getHeight() / 2 + mTargetHeight / 2);
canvas.drawBitmap(bitmap, null, dst, paint);
setDrawingCacheEnabled(false);
bitmap.recycle();
bitmap = null;
isCutImage = false;
//返回正方形图片
return targetBitmap;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mMatrix == null) {
return super.onTouchEvent(event);
}
float[] values = new float[9];
mMatrix.getValues(values);
float left = values[Matrix.MTRANS_X];
float top = values[Matrix.MTRANS_Y];
float right = (left + mBitmapWidth * values[Matrix.MSCALE_X]);
float bottom = (top + mBitmapHeight * values[Matrix.MSCALE_Y]);
float x = 0f;
float y = 0f;
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
CURR_MODE = MODE_DRAG;
mDownPoint.set(event.getX(), event.getY());
break;
case MotionEvent.ACTION_POINTER_DOWN:
if (getDistance(event) > 10f) {
CURR_MODE = MODE_ZOOM;
midPoint(mMiddlePoint, event);
mLastDistance = getDistance(event);
}
break;
case MotionEvent.ACTION_MOVE:
//如果当前模式为拖曳(单指触屏)
if (CURR_MODE == MODE_DRAG || CURR_MODE == MODE_POINTER_UP) {
if (CURR_MODE == MODE_DRAG) {
x = event.getX() - mDownPoint.x;
y = event.getY() - mDownPoint.y;
//left靠边
if (x + left > mCircleX) {
x = 0;
}
//right靠边
if (x + right < mCircleX + mTargetWidth) {
x = 0;
}
//top靠边
if (y + top > mCircleY) {
y = 0;
}
//bottom靠边
if (y + bottom < mCircleY + mTargetHeight) {
y = 0;
}
mMatrix.postTranslate(x, y);
mDownPoint.set(event.getX(), event.getY());
} else {
CURR_MODE = MODE_DRAG;
mDownPoint.set(event.getX(), event.getY());
}
} else {
//否则当前模式为缩放(双指触屏)
float distance = getDistance(event);
if (distance > 10f) {
float scale = distance / mLastDistance;
//left靠边
if (left >= mCircleX) {
mMiddlePoint.x = 0;
}
//right靠边
if (right <= mCircleX + mTargetWidth) {
mMiddlePoint.x = right;
}
//top靠边
if (top >= mCircleY) {
mMiddlePoint.y = 0;
}
//bottom靠边
if (bottom <= mCircleY + mTargetHeight) {
mMiddlePoint.y = bottom;
}
mTempMatrix.set(mMatrix);
mTempMatrix.postScale(scale, scale, mMiddlePoint.x, mMiddlePoint.y);
float[] temp_values = new float[9];
mTempMatrix.getValues(temp_values);
float temp_left = temp_values[Matrix.MTRANS_X];
float temp_top = temp_values[Matrix.MTRANS_Y];
float temp_right = (temp_left + mBitmapWidth * temp_values[Matrix.MSCALE_X]);
float temp_bottom = (temp_top + mBitmapHeight * temp_values[Matrix.MSCALE_Y]);
//靠边预判断
if (temp_left > mCircleX || temp_right < mCircleX + mTargetWidth ||
temp_top > mCircleY || temp_bottom < mCircleY + mTargetHeight) {
return true;
}
mMatrix.postScale(scale, scale, mMiddlePoint.x, mMiddlePoint.y);
mLastDistance = getDistance(event);
}
}
break;
case MotionEvent.ACTION_UP:
CURR_MODE = MODE_NONE;
break;
case MotionEvent.ACTION_POINTER_UP:
CURR_MODE = MODE_POINTER_UP;
break;
}
setImageMatrix(mMatrix);
return true;
}
/**
* 两点的距离
*/
private float getDistance(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);
}
/**
* 两点的中点
*/
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
/**
* 横向、纵向居中
*/
protected void center() {
float height = mBitmapHeight;
float width = mBitmapWidth;
float screenWidth = getWidth();
float screenHeight = getHeight();
float scale = 1f;
if (width >= height) {
scale = screenWidth / width;
if (scale * height < mTargetHeight) {
scale = mTargetHeight / height;
}
} else {
if (height <= screenHeight) {
scale = screenWidth / width;
} else {
scale = screenHeight / height;
}
if (scale * width < mTargetWidth) {
scale = mTargetWidth / width;
}
}
float deltaX = (screenWidth - width * scale) / 2f;
float deltaY = (screenHeight - height * scale) / 2f;
mMatrix.postScale(scale, scale);
mMatrix.postTranslate(deltaX, deltaY);
setImageMatrix(mMatrix);
}
/**
* 获得屏幕宽度
*/
public static int getScreenWidth(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.widthPixels;
}
/**
* 获得屏幕高度
*/
public static int getScreenHeight(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.heightPixels;
}
}