Files
HouseProperty/app/src/main/java/imageselector/view/ClipImageView.java

355 lines
12 KiB
Java
Raw Normal View History

2020-08-03 09:11:54 +08:00
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);
}
// 画入前景圆形蒙板层
2020-08-14 17:07:43 +08:00
int sc = canvas.saveLayer(rf, null, Canvas.ALL_SAVE_FLAG);
2020-08-03 09:11:54 +08:00
//画入矩形黑色半透明蒙板层
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;
}
}