仿作业帮图片裁剪-自定义View

效果图:


代码:

```

public class CropImageViewextends AppCompatImageView {

private ContextmContext;

    //裁剪框边框画笔

    private PaintmBorderPaint;

    //裁剪框九宫格画笔

    private PaintmGuidelinePaint;

    //绘制裁剪边框四个角的画笔

    private PaintmCornerPaint;

    //判断手指位置是否处于缩放裁剪框位置的范围:如果是当手指移动的时候裁剪框会相应的变化大小

    //否则手指移动的时候就是拖动裁剪框使之随着手指移动

    private float mScaleRadius;

    private float mCornerThickness;

    private float mBorderThickness;

    //四个角小短边的长度

    private float mCornerLength;

    //用来表示图片边界的矩形

    private RectFmBitmapRect =new RectF();

    //手指位置距离裁剪框的偏移量

    private PointFmTouchOffset =new PointF();

    private CropWindowEdgeSelectormPressedCropWindowEdgeSelector;

    private float oldW =0f;

    private float oldH =0f;

    private RectFodlBitmapRect =new RectF();

    public CropImageView(Context context) {

super(context);

        init(context);

    }

public CropImageView(Context context, AttributeSet attributeSet) {

super(context, attributeSet);

        init(context);

    }

/**

    * 里面的值暂时写死,也可以从AttributeSet里面来配置

    *

    * @param context

    */

    private void init(@NonNull Context context) {

mContext = context;

        mBorderPaint =new Paint(Paint.ANTI_ALIAS_FLAG);

        mBorderPaint.setStrokeWidth(UIUtil.dip2px(context, 3));

        mBorderPaint.setColor(Color.parseColor("#AA000000"));

        mGuidelinePaint =new Paint(Paint.ANTI_ALIAS_FLAG);

        mGuidelinePaint.setStyle(Paint.Style.STROKE);

        mGuidelinePaint.setStrokeWidth(UIUtil.dip2px(context, 1));

        mGuidelinePaint.setColor(Color.parseColor("#AAFFFFFF"));

        mCornerPaint =new Paint(Paint.ANTI_ALIAS_FLAG);

        mCornerPaint.setStyle(Paint.Style.STROKE);

        mCornerPaint.setStrokeWidth(UIUtil.dip2px(context, 5));

        mCornerPaint.setColor(Color.WHITE);

        mScaleRadius = UIUtil.dip2px(context, 24);

        mBorderThickness = UIUtil.dip2px(context, 3);

        mCornerThickness = UIUtil.dip2px(context, 5);

        mCornerLength = UIUtil.dip2px(context, 20);

    }

@Override

    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {

super.onLayout(changed, left, top, right, bottom);

        mBitmapRect = getBitmapRect();

        initCropWindow(mBitmapRect);

    }

@Override

    protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

        //绘制九宫格引导线

//        drawGuidelines(canvas);

        //绘制裁剪边框

        drawBorder(canvas);

        //绘制裁剪边框的四个角

        drawCorners(canvas);

    }

@Override

    public boolean onTouchEvent(MotionEvent event) {

if (!isEnabled()) {

return false;

        }

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

onActionDown(event.getX(), event.getY());

return true;

            case MotionEvent.ACTION_UP:

case MotionEvent.ACTION_CANCEL:

getParent().requestDisallowInterceptTouchEvent(false);

                onActionUp();

return true;

            case MotionEvent.ACTION_MOVE:

onActionMove(event.getX(), event.getY());

                getParent().requestDisallowInterceptTouchEvent(true);

return true;

            default:

return false;

        }

}

/**

    * 获取裁剪好的BitMap

*/

    public BitmapgetCroppedImage() {

final Drawable drawable = getDrawable();

        if (!(drawableinstanceof BitmapDrawable)) {

return null;

        }

final Bitmap originalBitmap = ((BitmapDrawable) drawable).getBitmap();

        double aY = originalBitmap.getHeight() / (float) (mBitmapRect.bottom -mBitmapRect.top);

        double aX = originalBitmap.getWidth() / (float) (mBitmapRect.right -mBitmapRect.left);

        float cropX = (float) (aX * (Edge.LEFT.getCoordinate() -mBitmapRect.left));

        float cropY = (float) (aY * (Edge.TOP.getCoordinate() -mBitmapRect.top));

        final float cropWidth = (float) (aX * Edge.getWidth());

        final float cropHeight = (float) (aY * Edge.getHeight());

        return Bitmap.createBitmap(originalBitmap,

                (int) cropX,

                (int) cropY,

                (int) cropWidth,

                (int) cropHeight

);

    }

/**

    * 获取图片ImageView周围的边界组成的RectF对象

    */

    private RectFgetBitmapRect() {

final Drawable drawable = getDrawable();

        if (drawable ==null) {

return new RectF();

        }

final float[] matrixValues =new float[9];

        getImageMatrix().getValues(matrixValues);

        final float scaleX = matrixValues[Matrix.MSCALE_X];

        final float scaleY = matrixValues[Matrix.MSCALE_Y];

        final float transX = matrixValues[Matrix.MTRANS_X];

        final float transY = matrixValues[Matrix.MTRANS_Y];

        final int drawableIntrinsicWidth = drawable.getIntrinsicWidth();

        final int drawableIntrinsicHeight = drawable.getIntrinsicHeight();

        final int drawableDisplayWidth = Math.round(drawableIntrinsicWidth * scaleX);

        final int drawableDisplayHeight = Math.round(drawableIntrinsicHeight * scaleY);

        final float left = Math.max(transX, 0);

        final float top = Math.max(transY, 0);

        final float right = Math.min(left + drawableDisplayWidth, getWidth());

        final float bottom = Math.min(top + drawableDisplayHeight, getHeight());

        return new RectF(left, top, right, bottom);

    }

/**

    * 初始化裁剪框

    *

    * @param bitmapRect

    */

    private boolean isOne =true;

    private void initCropWindow(@NonNull RectF bitmapRect) {

if (isOne) {

odlBitmapRect = bitmapRect;

            oldW = bitmapRect.right - bitmapRect.left;

            oldH = bitmapRect.bottom - bitmapRect.top;

            isOne =false;

            //裁剪框距离图片左右的padding值

            final float horizontalPadding =0.2f * bitmapRect.width();

            final float verticalPadding =0.2f * bitmapRect.height();

//            if (getHeight() > getWidth()) {

//                Edge.LEFT.initCoordinate(bitmapRect.left - ((bitmapRect.left - bitmapRect.right) / 4f));

//                Edge.TOP.initCoordinate(((bitmapRect.top + bitmapRect.bottom) / 2f) - ((bitmapRect.left - bitmapRect.right) / 8f));

//                Edge.RIGHT.initCoordinate(bitmapRect.right + ((bitmapRect.left - bitmapRect.right) / 4f));

//                Edge.BOTTOM.initCoordinate(((bitmapRect.top + bitmapRect.bottom) / 2f )+ ((bitmapRect.left - bitmapRect.right) / 8f));

//            }else {

//

//            }

            //初始化裁剪框上下左右四条边

            Edge.LEFT.initCoordinate(bitmapRect.left + horizontalPadding);

            Edge.TOP.initCoordinate(bitmapRect.top + verticalPadding);

            Edge.RIGHT.initCoordinate(bitmapRect.right - horizontalPadding);

            Edge.BOTTOM.initCoordinate(bitmapRect.bottom - verticalPadding);

        }else {

//变形后的宽高0>90  90->180  180->270  270->360

            float newW = bitmapRect.right - bitmapRect.left;

            float newH = bitmapRect.bottom - bitmapRect.top;

            float newWB = newH /oldW;

            float newWH = newW /oldH;

            float newT = bitmapRect.top + (newWB * (Edge.LEFT.getCoordinate() -odlBitmapRect.left));

            float newR = bitmapRect.right - (newWH * (Edge.TOP.getCoordinate() -odlBitmapRect.top));

            float newB = bitmapRect.bottom - (newWB * (odlBitmapRect.right - Edge.RIGHT.getCoordinate()));

            float newL = bitmapRect.left + (newWH * (odlBitmapRect.bottom - Edge.BOTTOM.getCoordinate()));

            Edge.TOP.initCoordinate(newT);

            Edge.RIGHT.initCoordinate(newR);

            Edge.BOTTOM.initCoordinate(newB);

            Edge.LEFT.initCoordinate(newL);

            odlBitmapRect = bitmapRect;

            oldW = bitmapRect.right - bitmapRect.left;

            oldH = bitmapRect.bottom - bitmapRect.top;

        }

}

private void drawGuidelines(@NonNull Canvas canvas) {

final float left = Edge.LEFT.getCoordinate();

        final float top = Edge.TOP.getCoordinate();

        final float right = Edge.RIGHT.getCoordinate();

        final float bottom = Edge.BOTTOM.getCoordinate();

        final float oneThirdCropWidth = Edge.getWidth() /3;

        final float x1 = left + oneThirdCropWidth;

        //引导线竖直方向第一条线

        canvas.drawLine(x1, top, x1, bottom, mGuidelinePaint);

        final float x2 = right - oneThirdCropWidth;

        //引导线竖直方向第二条线

        canvas.drawLine(x2, top, x2, bottom, mGuidelinePaint);

        final float oneThirdCropHeight = Edge.getHeight() /3;

        final float y1 = top + oneThirdCropHeight;

        //引导线水平方向第一条线

        canvas.drawLine(left, y1, right, y1, mGuidelinePaint);

        final float y2 = bottom - oneThirdCropHeight;

        //引导线水平方向第二条线

        canvas.drawLine(left, y2, right, y2, mGuidelinePaint);

    }

//画4边蒙版

    private void drawBorder(@NonNull Canvas canvas) {

//上蒙版

        canvas.drawRect(0f, 0f, getWidth(), Edge.TOP.getCoordinate(), mBorderPaint);

        //左蒙版

        canvas.drawRect(0f, Edge.TOP.getCoordinate() -0.22f, Edge.LEFT.getCoordinate(), Edge.BOTTOM.getCoordinate() +0.22f, mBorderPaint);

        //下蒙版

        canvas.drawRect(0f, Edge.BOTTOM.getCoordinate(), getWidth(), getHeight(), mBorderPaint);

        //右蒙版

        canvas.drawRect(Edge.RIGHT.getCoordinate(), Edge.TOP.getCoordinate() -0.22f, getWidth(), Edge.BOTTOM.getCoordinate() +0.22f, mBorderPaint);

    }

private void drawCorners(@NonNull Canvas canvas) {

final float left = Edge.LEFT.getCoordinate();

        final float top = Edge.TOP.getCoordinate();

        final float right = Edge.RIGHT.getCoordinate();

        final float bottom = Edge.BOTTOM.getCoordinate();

        //简单的数学计算

        final float lateralOffset = (mCornerThickness -mBorderThickness) /2f;

        final float startOffset =mCornerThickness - (mBorderThickness /2f);

        mCornerPaint.setStrokeCap(Paint.Cap.ROUND);

        mCornerPaint.setStrokeJoin(Paint.Join.ROUND);

        //左上角

        Path path1 =new Path();

        path1.moveTo(left - lateralOffset, top +mCornerLength);

        path1.lineTo(left - lateralOffset, top - lateralOffset);

        path1.lineTo(left +mCornerLength, top - lateralOffset);

        canvas.drawPath(path1, mCornerPaint);

        //右上角

        Path path2 =new Path();

        path2.moveTo(right -mCornerLength, top - lateralOffset);

        path2.lineTo(right + lateralOffset, top - lateralOffset);

        path2.lineTo(right + lateralOffset, top +mCornerLength);

        canvas.drawPath(path2, mCornerPaint);

//        //右上角右面的短线

//        canvas.drawLine(right + lateralOffset, top - startOffset, right + lateralOffset, top + mCornerLength, mCornerPaint);

//        //右上角上面的短线

//        canvas.drawLine(right + startOffset, top - lateralOffset, right - mCornerLength, top - lateralOffset, mCornerPaint);

        //左下角

        Path path3 =new Path();

        path3.moveTo(left - lateralOffset, bottom -mCornerLength);

        path3.lineTo(left - lateralOffset, bottom + lateralOffset);

        path3.lineTo(left +mCornerLength, bottom + lateralOffset);

        canvas.drawPath(path3, mCornerPaint);

//        canvas.drawLine(left - lateralOffset, bottom + startOffset, left - lateralOffset, bottom - mCornerLength, mCornerPaint);

//        //左下角底部的短线

//        canvas.drawLine(left - startOffset, bottom + lateralOffset, left + mCornerLength, bottom + lateralOffset, mCornerPaint);

        //右下角左面的短线

        Path path4 =new Path();

        path4.moveTo(right + lateralOffset, bottom -mCornerLength);

        path4.lineTo(right + lateralOffset, bottom + lateralOffset);

        path4.lineTo(right -mCornerLength, bottom + lateralOffset);

        canvas.drawPath(path4, mCornerPaint);

//        canvas.drawLine(right + lateralOffset, bottom + startOffset, right + lateralOffset, bottom - mCornerLength, mCornerPaint);

//        //右下角底部的短线

//        canvas.drawLine(right + startOffset, bottom + lateralOffset, right - mCornerLength, bottom + lateralOffset, mCornerPaint);

    }

/**

    * 处理手指按下事件

    *

    * @param x 手指按下时水平方向的坐标

    * @param y 手指按下时竖直方向的坐标

    */

    private void onActionDown(float x, float y) {

//获取边框的上下左右四个坐标点的坐标

        final float left = Edge.LEFT.getCoordinate();

        final float top = Edge.TOP.getCoordinate();

        final float right = Edge.RIGHT.getCoordinate();

        final float bottom = Edge.BOTTOM.getCoordinate();

        //获取手指所在位置位于图二种的A,B,C,D位置种哪一种

        mPressedCropWindowEdgeSelector = CatchEdgeUtil.getPressedHandle(x, y, left, top, right, bottom, mScaleRadius);

        if (mPressedCropWindowEdgeSelector !=null) {

//计算手指按下的位置与裁剪框的偏移量

            CatchEdgeUtil.getOffset(mPressedCropWindowEdgeSelector, x, y, left, top, right, bottom, mTouchOffset);

            invalidate();

        }

}

private void onActionUp() {

if (mPressedCropWindowEdgeSelector !=null) {

mPressedCropWindowEdgeSelector =null;

            invalidate();

        }

}

private void onActionMove(float x, float y) {

if (mPressedCropWindowEdgeSelector ==null) {

return;

        }

x +=mTouchOffset.x;

        y +=mTouchOffset.y;

        mPressedCropWindowEdgeSelector.updateCropWindow(x, y, mBitmapRect);

        invalidate();

    }

}

```

你可能感兴趣的:(仿作业帮图片裁剪-自定义View)