Android 照相图片剪切

先上效果图
在这里插入图片描述
自定义裁剪框view:

public class CropPhotoView extends View {
    private static final String TAG = "CropPhotoView";
    private float mPreviousTouchX = -1, mPreviousTouchY = -1;
    private int mCurrentTouchCornerIndex = -1;
    private final RectF mCropViewRect = new RectF();
    private final RectF mTempRect = new RectF();
    private final RectF mMaxRect = new RectF();

    private Paint mCropFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Paint mCropFrameCornersPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    float[] mCropGridCorners;
    private int mCropRectCornerTouchAreaLineLength;
    private int mCropRectMinSize;

    {
        mCropRectCornerTouchAreaLineLength = getResources().getDimensionPixelSize(R.dimen.ucrop_default_crop_rect_corner_touch_area_line_length);
        mCropRectMinSize = getResources().getDimensionPixelSize(R.dimen.ucrop_default_crop_rect_min_size);
        mCropFramePaint.setColor(getResources().getColor(R.color.color_5164E0));
        mCropFramePaint.setStrokeWidth(DensityUtils.dp2px(getContext(), 2));
        mCropFramePaint.setStyle(Paint.Style.STROKE);
        mCropFrameCornersPaint.setColor(getResources().getColor(R.color.color_5164E0));
        mCropFrameCornersPaint.setStrokeWidth(DensityUtils.dp2px(getContext(), 4));
        mCropFrameCornersPaint.setStyle(Paint.Style.STROKE);
    }

    public CropPhotoView(Context context) {
        super(context);
    }

    public CropPhotoView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawRect(mCropViewRect, mCropFramePaint);

        canvas.save();

        mTempRect.set(mCropViewRect);
        mTempRect.inset(mCropRectCornerTouchAreaLineLength, -mCropRectCornerTouchAreaLineLength);
        canvas.clipRect(mTempRect, Region.Op.DIFFERENCE);

        mTempRect.set(mCropViewRect);
        mTempRect.inset(-mCropRectCornerTouchAreaLineLength, mCropRectCornerTouchAreaLineLength);
        canvas.clipRect(mTempRect, Region.Op.DIFFERENCE);

        canvas.drawRect(mCropViewRect, mCropFrameCornersPaint);

        canvas.restore();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mCropViewRect.isEmpty()) {
            return false;
        }

        float x = event.getX();
        float y = event.getY();
        if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
            mCurrentTouchCornerIndex = getCurrentTouchIndex(x, y);
            boolean shouldHandle = mCurrentTouchCornerIndex != -1;
            if (!shouldHandle) {
                mPreviousTouchX = -1;
                mPreviousTouchY = -1;
            } else if (mPreviousTouchX < 0) {
                mPreviousTouchX = x;
                mPreviousTouchY = y;
            }
            return shouldHandle;
        }

        if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_MOVE) {
            if (event.getPointerCount() == 1 && mCurrentTouchCornerIndex != -1) {
                x = Math.min(Math.max(x, getPaddingLeft()), getWidth() - getPaddingRight());
                y = Math.min(Math.max(y, getPaddingTop()), getHeight() - getPaddingBottom());
                updateCropViewRect(x, y);

                mPreviousTouchX = x;
                mPreviousTouchY = y;

                return true;
            }
        }

        if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) {
            mPreviousTouchX = -1;
            mPreviousTouchY = -1;
            mCurrentTouchCornerIndex = -1;
        }

        return false;
    }


    public void setRect(int l, int t, int r, int b) {
        mMaxRect.set(l, t, r, b);
        mCropViewRect.set(l, t, r, b);
        mTempRect.set(l, t, r, b);
        updateGridPoints();
        postInvalidate();
    }

    /**
     * * The order of the corners is:
     * 0------->1
     * ^        |
     * |   4    |
     * |        v
     * 3<-------2
     */
    private void updateCropViewRect(float touchX, float touchY) {
        mTempRect.set(mCropViewRect);
        Log.e(TAG, "updateCropViewRect: " + mCurrentTouchCornerIndex);
        switch (mCurrentTouchCornerIndex) {
            // resize rectangle
            case 0:
                mTempRect.set(Math.max(touchX, mMaxRect.left), Math.max(touchY, mMaxRect.top), mCropViewRect.right, mCropViewRect.bottom);
                break;
            case 1:
                mTempRect.set(mCropViewRect.left, Math.max(touchY, mMaxRect.top), Math.min(touchX, mMaxRect.right), mCropViewRect.bottom);
                break;
            case 2:
                mTempRect.set(mCropViewRect.left, mCropViewRect.top, Math.min(touchX, mMaxRect.right), Math.min(touchY, mMaxRect.bottom));
                break;
            case 3:
                mTempRect.set(Math.max(touchX, mMaxRect.left), mCropViewRect.top, mCropViewRect.right, Math.min(touchY, mMaxRect.bottom));
                break;
            // move rectangle
            case 4:
                mTempRect.offset((mTempRect.left + touchX - mPreviousTouchX < mMaxRect.left || mTempRect.right + touchX - mPreviousTouchX > mMaxRect.right) ? 0 : touchX - mPreviousTouchX,
                        (mTempRect.top + touchY - mPreviousTouchY < mMaxRect.top || mTempRect.bottom + touchY - mPreviousTouchY > mMaxRect.bottom) ? 0 : touchY - mPreviousTouchY);
                if (mTempRect.left > getLeft() && mTempRect.top > getTop()
                        && mTempRect.right < getRight() && mTempRect.bottom < getBottom()) {
                    mCropViewRect.set(mTempRect);
                    updateGridPoints();
                    postInvalidate();
                }
                return;
        }

        boolean changeHeight = mTempRect.height() >= mCropRectMinSize;
        boolean changeWidth = mTempRect.width() >= mCropRectMinSize;
        mCropViewRect.set(
                changeWidth ? mTempRect.left : mCropViewRect.left,
                changeHeight ? mTempRect.top : mCropViewRect.top,
                changeWidth ? mTempRect.right : mCropViewRect.right,
                changeHeight ? mTempRect.bottom : mCropViewRect.bottom);

        if (changeHeight || changeWidth) {
            updateGridPoints();
            postInvalidate();
        }
    }

    private void updateGridPoints() {
        mCropGridCorners = RectUtils.getCornersFromRect(mCropViewRect);
    }

    /**
     * * The order of the corners in the float array is:
     * 0------->1
     * ^        |
     * |   4    |
     * |        v
     * 3<-------2
     *
     * @return - index of corner that is being dragged
     */
    private int getCurrentTouchIndex(float touchX, float touchY) {
        int closestPointIndex = -1;
        double closestPointDistance = getResources().getDimensionPixelSize(R.dimen.ucrop_default_crop_rect_corner_touch_threshold);
        for (int i = 0; i < 8; i += 2) {
            double distanceToCorner = Math.sqrt(Math.pow(touchX - mCropGridCorners[i], 2)
                    + Math.pow(touchY - mCropGridCorners[i + 1], 2));
            if (distanceToCorner < closestPointDistance) {
                closestPointDistance = distanceToCorner;
                closestPointIndex = i / 2;
            }
        }

        if (closestPointIndex < 0 && mCropViewRect.contains(touchX, touchY)) {
            return 4;
        }

        return closestPointIndex;
    }

    public Bitmap getCropBitmap(Bitmap source) {
        if (mCropViewRect.contains(mMaxRect)) {
            Log.e(TAG, "getCropBitmap: mCropViewRect.contains(mMaxRect)=true");
            return source;
        }
        return Bitmap.createBitmap(source,
                (int) ((mCropViewRect.left - mMaxRect.left) / mMaxRect.width() * source.getWidth()),
                (int) ((mCropViewRect.top - mMaxRect.top) / mMaxRect.height() * source.getHeight()),
                (int) (mCropViewRect.width() / mMaxRect.width() * source.getWidth()),
                (int) (mCropViewRect.height() / mMaxRect.height() * source.getHeight()));
    }
}

布局文件:

 <RelativeLayout
        android:id="@+id/rl"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_toStartOf="@+id/ll_control">

        <ImageView
            android:id="@+id/iv_show"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:scaleType="fitXY" />

        <com.xxxx.common.widget.CropPhotoView
            android:id="@+id/cpv"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </RelativeLayout>

ImageView负责显示图片,
CropPhotoView 负责裁剪框。

自定义view借鉴uCrop裁剪框view
由于产品设定比较简单且与uCrop相差甚多,自己借鉴写了一个简单的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值