package com.anthony.imagepicker.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.widget.ImageView;
import com.anthony.imagepicker.R;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/**
* ================================================
* 作 者:廖子尧
* 版 本:1.0
* 创建日期:2016/1/7
* 描 述:
* Matrix 的9个值分别为 缩放 平移 倾斜
* MSCALE_X MSKEW_X MTRANS_X
* MSKEW_Y MSCALE_Y MTRANS_Y
* MPERSP_0 MPERSP_1 MPERSP_2
* 修订历史:
* ================================================
*/
public class CropImageView extends ImageView {
/******************************** 中间的FocusView绘图相关的参数 *****************************/
public enum Style {
RECTANGLE, CIRCLE
}
private Style[] styles = {Style.RECTANGLE, Style.CIRCLE};
private int mMaskColor = 0xAF000000; //暗色
private int mBorderColor = 0xAA808080; //焦点框的边框颜色
private int mBorderWidth = 1; //焦点边框的宽度(画笔宽度)
private int mFocusWidth = 250; //焦点框的宽度
private int mFocusHeight = 250; //焦点框的高度
private int mDefaultStyleIndex = 0; //默认焦点框的形状
private Style mStyle = styles[mDefaultStyleIndex];
private Paint mBorderPaint = new Paint();
private Path mFocusPath = new Path();
private RectF mFocusRect = new RectF();
/******************************** 图片缩放位移控制的参数 ************************************/
private static final float MAX_SCALE = 4.0f; //最大缩放比,图片缩放后的大小与中间选中区域的比值
private static final int NONE = 0; // 初始化
private static final int DRAG = 1; // 拖拽
private static final int ZOOM = 2; // 缩放
private static final int ROTATE = 3; // 旋转
private static final int ZOOM_OR_ROTATE = 4; // 缩放或旋转
private static final int SAVE_SUCCESS = 1001; // 缩放或旋转
private static final int SAVE_ERROR = 1002; // 缩放或旋转
private int mImageWidth;
private int mImageHeight;
private int mRotatedImageWidth;
private int mRotatedImageHeight;
private Matrix matrix = new Matrix(); //图片变换的matrix
private Matrix savedMatrix = new Matrix(); //开始变幻的时候,图片的matrix
private PointF pA = new PointF(); //第一个手指按下点的坐标
private PointF pB = new PointF(); //第二个手指按下点的坐标
private PointF midPoint = new PointF(); //两个手指的中间点
private PointF doubleClickPos = new PointF(); //双击图片的时候,双击点的坐标
private PointF mFocusMidPoint = new PointF(); //中间View的中间点
private int mode = NONE; //初始的模式
private long doubleClickTime = 0; //第二次双击的时间
private double rotation = 0; //手指旋转的角度,不是90的整数倍,可能为任意值,需要转换成level
private float oldDist = 1; //双指第一次的距离
private int sumRotateLevel = 0; //旋转的角度,90的整数倍
private float mMaxScale = MAX_SCALE;//程序根据不同图片的大小,动态得到的最大缩放比
private boolean isInited = false; //是否经过了 onSizeChanged 初始化
private boolean mSaving = false; //是否正在保存
private static Handler mHandler = new InnerHandler();
public CropImageView(Context context) {
this(context, null);
}
public CropImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CropImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mFocusWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mFocusWidth, getResources().getDisplayMetrics());
mFocusHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mFocusHeight, getResources().getDisplayMetrics());
mBorderWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mBorderWidth, getResources().getDisplayMetrics());
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CropImageView);
mMaskColor = a.getColor(R.styleable.CropImageView_cropMaskColor, mMaskColor);
mBorderColor = a.getColor(R.styleable.CropImageView_cropBorderColor, mBorderColor);
mBorderWidth = a.getDimensionPixelSize(R.styleable.CropImageView_cropBorderWidth, mBorderWidth);
mFocusWidth = a.getDimensionPixelSize(R.styleable.CropImageView_cropFocusWidth, mFocusWidth);
mFocusHeight = a.getDimensionPixelSize(R.styleable.CropImageView_cropFocusHeight, mFocusHeight);
mDefaultStyleIndex = a.getInteger(R.styleable.CropImageView_cropStyle, mDefaultStyleIndex);
mStyle = styles[mDefaultStyleIndex];
a.recycle();
//只允许图片为当前的缩放模式
setScaleType(ScaleType.MATRIX);
}
@Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
initImage();
}
@Override
public void setImageDrawable(Drawable drawable) {
super.setImageDrawable(drawable);
initImage();
}
@Override
public void setImageResource(int resId) {
super.setImageResource(resId);
initImage();
}
@Override
public void setImageURI(Uri uri) {
super.setImageURI(uri);
initImage();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
isInited = true;
initImage();
}
/** 初始化图片和焦点框 */
private void initImage() {
Drawable d = getDrawable();
if (!isInited || d == null) return;
mode = NONE;
matrix = getImageMatrix();
mImageWidth = mRotatedImageWidth = d.getIntrinsicWidth();
mImageHeight = mRotatedImageHeight = d.getIntrinsicHeight();
//计算出焦点框的中点的坐标和上、下、左、右边的x或y的值
int viewWidth = getWidth();
int viewHeight = getHeight();
float midPointX = viewWidth / 2;
float midPointY = viewHeight / 2;
mFocusMidPoint = new PointF(midPointX, midPointY);
if (mStyle == Style.CIRCLE) {
int focusSize = Math.min(mFocusWidth, mFocusHeight);
mFocusWidth = focusSize;
mFocusHeight = focusSize;
}
mFocusRect.left = mFocusMidPoint.x - mFocusWidth / 2;
mFocusRect.right = mFocusMidPoint.x + mFocusWidth / 2;
mFocusRect.top = mFocusMidPoint.y - mFocusHeight / 2;
mFocusRect.bottom = mFocusMidPoint.y + mFocusHeight / 2;
//适配焦点框的缩放比例(图片的最小边不小于焦点框的最小边)
float fitFocusScale = getScale(mImageWidth, mImageHeight, mFocusWidth, mFocusHeight, true);
mMaxScale = fitFocusScale * MAX_SCALE;
//适配显示图片的ImageView的缩放比例(图片至少有一边是铺满屏幕的显示的情形)
float fitViewScale = getScale(mImageWidth, mImageHeight, viewWidth, viewHeight, false);
//确定最终的缩放比例,在适配焦点框的前提下适配显示图片的ImageView,
//方案:首先满足适配焦点框,如果还能适配显示图片的ImageView,则适配它,即取缩放比例的最大值。
//采取这种方案的原因:有可能图片很长或者很高,适配了ImageView的时候可能会宽/高已经小于焦点框的宽/高
float scale = fitViewScale > fitFocusScale ? fitViewScale : fitFocusScale;
//图像中点为中心进行缩放
matrix.setScale(scale, scale, mImageWidth / 2, mImageHeight / 2);
float[] mImageMatrixValues = new float[9];
matrix.getValues(mImageMatrixValues); //获取缩放后的mImageMatrix的值
float transX = mFocusMidPoint.x - (mImageMatrixValues[2] + mImageWidth * mImageMatrixValues[0] / 2); //X轴方向的位移
float transY = mFocusMidPoint.y - (mImageMatrixValues[5] + mImageHeight * mImageMatrixValues[4] / 2); //Y轴方向的位移
matrix.postTranslate(transX, transY);
setImageMatrix(matrix);
invalidate();
}
/** 计算边界缩放比例 isMinScale 是否最小比例,true 最小缩放比例, false 最大缩放比例 */
private float getScale(int bitmapWidth, int bitmapHeight, int minWidth, int minHeight, boolean isMinScale) {
float scale;
float scaleX = (float) minWidth / bitmapWidth;
float scaleY = (float) minHeight / bitmapHeight;
if (isMinScale) {
scale = scaleX > scaleY ? scaleX : scaleY;
} else {
scale = scaleX < scaleY ? scaleX : scaleY;
}
return scale;
}
/** 绘制焦点框 */
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (Style.RECTANGLE == mStyle) {
mFocusPath.addRect(mFocusRect, Path.Direction.CCW);
canvas.save();
canvas.clipRect(0, 0, getWidth(), getHeight());
canvas.clipPath(mFocusPath, Region.Op.DIFFERENCE);
canvas.drawColor(mMaskColor);
canvas.restore();
} else if (Style.CIRCLE == mStyle) {
float radius = Math.min((mFocusRect.right - mFocusRect.left) / 2, (mFocusRect.bottom - mFocusRect.top) / 2);
mFocusPath.addCircle(mFocusMidPoint.x, mFocusMidPoint.y, radius, Path.Direction.CCW);
canvas.save();
canvas.clipRect(0, 0, getWidth(), getHeight());
canvas.clipPath(mFocusPath, Region.Op.DIFFERENCE);
canvas.drawColor(mMaskColor);
canvas.restore();
}
mBorderPaint.setColor(mBorderColor);
mBorderPaint.setStyle(Paint.Style.STROKE);
mBorderPaint.setStrokeWidth(mBorderWidth);
mBorderPaint.setAntiAlias(true);
canvas.drawPath(mFocusPath, mBorderPaint);
mFocusPath.reset();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mSaving || null == getDrawable()) {
return super.onTouchEvent(event);
}
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: //第一个点按下
savedMatrix.set(matrix); //以后每次需要变换的时候,以现在的状态为基础进行变换
pA.set(event.getX(), event.getY());
pB.set(event.getX(), event.getY());
mode = DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN: //第二个点按下
if (event.getActionIndex() > 1) break;
pA.set(event.getX(0), event.getY(0));
pB.set(event.getX(1), event.getY(1));
midPoint.set((pA.x + pB.x) / 2, (pA.y + pB.y) / 2);
oldDist = spacing(pA, pB);
savedMatrix.set(matrix); //以后每次需要变换的时候,以现在的状态为基础进行变换
if (oldDist > 10f) mode = ZOOM_OR_ROTATE;//两点之间的距离大于10才有效
break;
case MotionEvent.ACTION_MOVE:
if (mode == ZOOM_OR_ROTATE) {
PointF pC = new PointF(event.getX(1) - event.getX(0) + pA.x, event.getY(1) - event.getY(0) + pA.y);
double a = spacing(pB.x, pB.y, pC.x, pC.y);
double b = spacing(pA.x, pA.y, pC.x, pC.y);
double c = spacing(pA.x, pA.y, pB.x, pB.y);
if (a >= 10) {
double cosB = (a * a + c * c - b * b) / (2 * a * c);
double angleB = Math.acos(cosB);
double PID4 = Math.PI / 4;
//旋转时,默认角度在 45 - 135 度之间
if (angleB > PID4 && angleB < 3 * PID4) mode = ROTATE;
else mode = ZOOM;
}
}
if (mode == DRAG) {
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - pA.x, event.getY() - pA.y);
fixTranslation();
setImageMatrix(matrix);
} else if (mode == ZOOM) {
float newDist = spacing(event.getX(0), event.getY(0), event.getX(1), event.getY(1));
if (newDist > 10f) {
matrix.set(savedMatrix);
// 这里之所以用 maxPostScale 矫正一下,主要是防止缩放到最大时,继续缩放图片会产生位移
float tScale = Math.min(newDist / oldDist, maxPostScale());
if (tScale != 0) {
matrix.postScale(tScale, tScale, midPoint.x, midPoint.y);
fixScale();
fixTranslation();
setImageMatrix(matrix);
}
}
} else if (mode == ROTATE) {
PointF pC = new PointF(event.getX(1) - event.getX(0) + pA.x, event.getY(1) - event.getY(0) + pA.y);
double a = spacing(pB.x, pB.y, pC.x, pC.y);
double b = spacing(pA.x, pA.y, pC.x, pC.y);
double c = spacing(pA.x, pA.y, pB.x, pB.y);
if (b > 10) {
double cosA = (b * b + c * c - a * a) / (2 * b * c);
double angleA = Math.acos(cosA);
double ta = pB.y - pA.y;
double tb = pA.x - pB.x;
double tc = pB.x * pA.y - pA.x * pB.y;
double td = ta * pC.x + tb * pC.y + tc;
if (td > 0) {
angleA = 2 * Math.PI - angleA;
}
rotation = angleA;
matrix.set(savedMatrix);
matrix.postRotate((float) (rotation * 180 / Math.PI), midPoint.x, midPoint.y);
setImageMatrix(matrix);
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
if (mode == DRAG) {
if (spacing(pA, pB) < 50) {
long now = System.currentTimeMillis();
if (now - doubleClickTime < 500 && spacing(pA, doubleClickPos) < 50) {
doubleClick(pA.x, pA.y);
now = 0;
}
doubleClickPos.set(pA);
doubleClickTime = now;
}
} else if (mode == ROTATE) {
int rotateLevel = (int) Math.floor((rotation + Math.PI / 4) / (Math.PI / 2));
if (rotateLevel == 4) rotateLevel = 0;
matrix.set(savedMatrix);
matrix.postRotate(90 * rotateLevel, midPoint.x, midPoint.y);
if (rotateLevel == 1 || rotateLevel == 3) {
int tmp = mRotatedImageWidth;
mRotatedImageWidth = mRotatedImageHeight;
mRotatedImageHeight = tmp;
}
fixScale();
fixTranslation();
setImageMatrix(matrix);
sumRotateLevel += rotateLevel;
}
mode = NONE;
break;
}
//解决部分机型无法拖动的问题
ViewCompat.postInvalidateOnAnimation(this);
return true;
}
/** 修正图片的缩放比 */
private void fixScale() {
float imageMatrixValues[] = new float[9];
matrix.getValues(imageMatrixValues);
float currentScale = Math.abs(imageMatrixValues[0]) + Math.abs(imageMatrixValues[1]);
float minScale = getScale(mRotatedImageWidth, mRotatedImageHeight, mFocusWidth, mFocusHeight, true);
mMaxScale = minScale * MAX_SCALE;
//保证图片最小是占满中间的焦点空间
if (currentScale < minScale) {
float scale = minScale / currentScale;
matrix.postScale(scale, scale);
} else if (currentScale > mMaxScale) {
float scale = mMaxScale / currentScale;
matrix.postScale(scale, scale);
}
}
/** 修正图片的位移 */
private void fixTranslation() {
RectF imageRect = new RectF(0, 0, mImageWidth, mImageHeight);
matrix.mapRect(imageRect); //获取当前图片(缩放以后的)相对于当前控件的位置区域,超过控件的上边缘或左边缘为负
float deltaX = 0, deltaY = 0;
if (imageRect.left > mFocusRect.left) {
deltaX = -imageRect.left + mFocusRect.left;
} else if (imageRect.right < mFocusRect.right) {
deltaX = -imageRect.right + mFocusRect.right;
}
if (imageRect.top > mFocusRect.top) {
deltaY = -imageRect.top + mFocusRect.top;
} else if (imageRect.bottom < mFocusRect.bottom) {
deltaY = -imageRect.bottom + mFocusRect.bottom;
}
matrix.postTranslate(deltaX, deltaY);
}
/** 获取当前图片允许的最大缩放比 */
private float maxPostScale() {
float imageMatrixValues[] = new float[9];
matrix.getValues(imageMatrixValues);
float curScale = Math.abs(imageMatrixValues[0]) + Math.abs(imageMatrixValues[1]);
return mMaxScale / curScale;
}
/** 计算两点之间的距离 */
private float spacing(float x1, float y1, float x2, float y2) {
float x = x1 - x2;
float y = y1 - y2;
return (float) Math.sqrt(x * x + y * y);
}
/** 计算两点之间的距离 */
private float spacing(PointF pA, PointF pB) {
return spacing(pA.x, pA.y, pB.x, pB.y);
}
/** 双击触发的方法 */
private void doubleClick(float x, float y) {
float p[] = new float[9];
matrix.getValues(p);
float curScale = Math.abs(p[0]) + Math.abs(p[1]);
float minScale = getScale(mRotatedImageWidth, mRotatedImageHeight, mFocusWidth, mFocusHeight, true);
if (curScale < mMaxScale) {
//每次双击的时候,缩放加 minScale
float toScale = Math.min(curScale + minScale, mMaxScale) / curScale;
matrix.postScale(toScale, toScale, x, y);
} else {
float toScale = minScale / curScale;
matrix.postScale(toScale, toScale, x, y);
fixTranslation();
}
setImageMatrix(matrix);
}
/**
* @param expectWidth 期望的宽度
* @param exceptHeight 期望的高度
* @param isSaveRectangle 是否按矩形区域保存图片
* @return 裁剪后的Bitmap
*/
public Bitmap getCropBitmap(int expectWidth, int exceptHeight, boolean isSaveRectangle) {
if (expectWidth <= 0 || exceptHeight < 0) return null;
Bitmap srcBitmap = ((BitmapDrawable) getDrawable()).getBitmap();
srcBitmap = rotate(srcBitmap, sumRotateLevel * 90); //最好用level,因为角度可能不是90的整数
return makeCropBitmap(srcBitmap, mFocusRect, getImageMatrixRect(), expectWidth, exceptHeight, isSaveRectangle);
}
/**
* @param bitmap 要旋转的图片
* @param degrees 选择的角度(单位 度)
* @return 旋转后的Bitmap
*/
private Bitmap rotate(Bitmap bitmap, int degrees) {
if (degrees != 0 && bitmap != null) {
Matrix matrix = new Matrix();
matrix.setRotate(degrees, (float) bitmap.getWidth() / 2, (float) bitmap.getHeight() / 2);
try {
Bitmap rotateBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
if (bitmap != rotateBitmap) {
// bitmap.recycle();
return rotateBitmap;
}
} catch (OutOfMemoryError ex) {
ex.printStackTrace();
}
}
return bitmap;
}
/**
* @return 获取当前图片显示的矩形区域
*/
private RectF getImageMatrixRect() {
RectF rectF = new RectF();
rectF.set(0, 0, getDrawable().getIntrinsicWidth(), getDrawable().getIntrinsicHeight());
matrix.mapRect(rectF);
return rectF;
}
/**
* @param bitmap 需要裁剪的图片
* @param focusRect 中间需要裁剪的矩形区域
* @param imageMatrixRect 当前图片在屏幕上的显示矩形区域
* @param expectWidth 希望获得的图片宽度,如果图片宽度不足时,拉伸图片
* @param exceptHeight 希望获得的图片高度,如果图片高度不足时,拉伸图片
* @param isSaveRectangle 是否希望按矩形区域保存图片
* @return 裁剪后的图片的Bitmap
*/
private Bitmap makeCropBitmap(Bitmap bitmap, RectF focusRect, RectF imageMatrixRect, int expectWidth, int exceptHeight, boolean isSaveRectangle) {
float scale = imageMatrixRect.width() / bitmap.getWidth();
int left = (int) ((focusRect.left - imageMatrixRect.left) / scale);
int top = (int) ((focusRect.top - imageMatrixRect.top) / scale);
int width = (int) (focusRect.width() / scale);
int height = (int) (focusRect.height() / scale);
if (left < 0) left = 0;
if (top < 0) top = 0;
if (left + width > bitmap.getWidth()) width = bitmap.getWidth() - left;
if (top + height > bitmap.getHeight()) height = bitmap.getHeight() - top;
try {
bitmap = Bitmap.createBitmap(bitmap, left, top, width, height);
if (expectWidth != width || exceptHeight != height) {
bitmap = Bitmap.createScaledBitmap(bitmap, expectWidth, exceptHeight, true);
if (mStyle == CropImageView.Style.CIRCLE && !isSaveRectangle) {
//如果是圆形,就将图片裁剪成圆的
int length = Math.min(expectWidth, exceptHeight);
int radius = length / 2;
Bitmap circleBitmap = Bitmap.createBitmap(length, length, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(circleBitmap);
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Paint paint = new Paint();
paint.setShader(bitmapShader);
canvas.drawCircle(expectWidth / 2f, exceptHeight / 2f, radius, paint);
bitmap = circleBitmap;
}
}
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
return bitmap;
}
/**
* @param folder 希望保存的文件夹
* @param expectWidth 希望保存的图片宽度
* @param exceptHeight 希望保存的图片高度
* @param isSaveRectangle 是否希望按矩形区域保存图片
*/
public void saveBitmapToFile(File folder, int expectWidth, int exceptHeight, boolean isSaveRectangle) {
if (mSaving) return;
mSaving = true;
final Bitmap croppedImage = getCropBitmap(expectWidth, exceptHeight, isSaveRectangle);
Bitmap.CompressFormat outputFormat = Bitmap.CompressFormat.JPEG;
File saveFile = createFile(folder, "IMG_", ".jpg");
if (mStyle == CropImageView.Style.CIRCLE && !isSaveRectangle) {
outputFormat = Bitmap.CompressFormat.PNG;
saveFile = createFile(folder, "IMG_", ".png");
}
final Bitmap.CompressFormat finalOutputFormat = outputFormat;
final File finalSaveFile = saveFile;
new Thread() {
@Override
public void run() {
saveOutput(croppedImage, finalOutputFormat, finalSaveFile);
}
}.start();
}
/** 根据系统时间、前缀、后缀产生一个文件 */
private File createFile(File folder, String prefix, String suffix) {
if (!folder.exists() || !folder.isDirectory()) folder.mkdirs();
try {
File nomedia = new File(folder, ".nomedia"); //在当前文件夹底下创建一个 .nomedia 文件
if (!nomedia.exists()) nomedia.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA);
String filename = prefix + dateFormat.format(new Date(System.currentTimeMillis())) + suffix;
return new File(folder, filename);
}
/** 将图片保存在本地 */
private void saveOutput(Bitmap croppedImage, Bitmap.CompressFormat outputFormat, File saveFile) {
OutputStream outputStream = null;
try {
outputStream = getContext().getContentResolver().openOutputStream(Uri.fromFile(saveFile));
if (outputStream != null) croppedImage.compress(outputFormat, 90, outputStream);
Message.obtain(mHandler, SAVE_SUCCESS, saveFile).sendToTarget();
} catch (IOException ex) {
ex.printStackTrace();
Message.obtain(mHandler, SAVE_ERROR, saveFile).sendToTarget();
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
mSaving = false;
croppedImage.recycle();
}
private static class InnerHandler extends Handler {
public InnerHandler() {
super(Looper.getMainLooper());
}
@Override
public void handleMessage(Message msg) {
File saveFile = (File) msg.obj;
switch (msg.what) {
case SAVE_SUCCESS:
if (mListener != null) mListener.onBitmapSaveSuccess(saveFile);
break;
case SAVE_ERROR:
if (mListener != null) mListener.onBitmapSaveError(saveFile);
break;
}
}
}
/** 图片保存完成的监听 */
private static OnBitmapSaveCompleteListener mListener;
public interface OnBitmapSaveCompleteListener {
void onBitmapSaveSuccess(File file);
void onBitmapSaveError(File file);
}
public void setOnBitmapSaveCompleteListener(OnBitmapSaveCompleteListener listener) {
mListener = listener;
}
/** 返回焦点框宽度 */
public int getFocusWidth() {
return mFocusWidth;
}
/** 设置焦点框的宽度 */
public void setFocusWidth(int width) {
mFocusWidth = width;
initImage();
}
/** 获取焦点框的高度 */
public int getFocusHeight() {
return mFocusHeight;
}
/** 设置焦点框的高度 */
public void setFocusHeight(int height) {
mFocusHeight = height;
initImage();
}
/** 返回阴影颜色 */
public int getMaskColor() {
return mMaskColor;
}
/** 设置阴影颜色 */
public void setMaskColor(int color) {
mMaskColor = color;
invalidate();
}
/** 返回焦点框边框颜色 */
public int getFocusColor() {
return mBorderColor;
}
/** 设置焦点框边框颜色 */
public void setBorderColor(int color) {
mBorderColor = color;
invalidate();
}
/** 返回焦点框边框绘制宽度 */
public float getBorderWidth() {
return mBorderWidth;
}
/** 设置焦点边框宽度 */
public void setBorderWidth(int width) {
mBorderWidth = width;
invalidate();
}
/** 设置焦点框的形状 */
public void setFocusStyle(Style style) {
this.mStyle = style;
invalidate();
}
/** 获取焦点框的形状 */
public Style getFocusStyle() {
return mStyle;
}
}