Android 仿PC端QQ自由截圖,可支持一次截多個(gè)區(qū)域

仿PC端QQ截圖,可任意截圖,這里只做了矩形這一種形狀,可同時(shí)支持截取多個(gè)區(qū)域,支持撤銷上次截圖,重新截取。

實(shí)現(xiàn)原理:

自定義SurfaceView,在SurfaceView上繪制具有一個(gè)可拉伸,移動(dòng)的矩形框,當(dāng)點(diǎn)擊截圖按鈕后,計(jì)算矩形框的坐標(biāo)值及原圖尺寸,通過比例將矩形框的坐標(biāo)值轉(zhuǎn)化到原圖中相對(duì)應(yīng)的坐標(biāo),然后進(jìn)行裁剪。

項(xiàng)目源碼:https://github.com/LeeVanie/CavansRect

實(shí)現(xiàn)代碼:

public class CustomSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable, Handler.Callback {?

?// SurfaceHolder private SurfaceHolder mSurfaceHolder;

? ? /**

? ? * 屏幕尺寸

? ? */? ??

private int viewWidth;

? ? private int viewHeight;

? ? // 線寬? ??

private int StrokeWidth = 5;

? ? private boolean startDraw;

? ? //半徑? ??

private int radius;

? ? // Path? ??

private Path mPath = new Path();

? ? // 畫筆? ??

private Paint mpaint = new Paint();

? ? private Canvas canvas;

? ? //滑板背景(保存繪制的圖片)? ??

private Bitmap saveBitmap;

? ? //圖像? ??

Bitmap bitmap;

? ? // 圖片路徑? ??

private String urlPath;

? ? private List drawPathList = new ArrayList<>();

? ? /**

? ? * X 、 Y 方向的圖片和屏幕比例

? ? */? ? private float scaleX, scaleY;

? ? /**

? ? * 0矩形

? ? * 1撤回

? ? */? ??

private static int state = 0;

? ? public void setState(int state) {

? ? ? ? this.state = state;

? ? }

? ? public CustomSurfaceView(Context context, String url, boolean s) {

? ? ? ? this(context, null);

? ? ? ? this.urlPath = url;

? ? ? ? saveBitmap = Bitmap.createBitmap(720, 1000, Bitmap.Config.ARGB_8888);

? ? }

? ? public CustomSurfaceView(Context context, AttributeSet attrs) {

? ? ? ? this(context, attrs, 0);

? ? }

? ? public CustomSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {

? ? ? ? super(context, attrs, defStyleAttr);

? ? ? ? initView(); // 初始化? ?

?}

? ? private void initView() {

? ? ? ? setMeasuredDimension(720, 1000);

? ? ? ? mSurfaceHolder = getHolder();

? ? ? ? mSurfaceHolder.addCallback(this);

? ? ? ? mSurfaceHolder.setFormat(PixelFormat.TRANSPARENT);

? ? ? ? setFocusable(true);

? ? ? ? setFocusableInTouchMode(true);

? ? ? ? this.setKeepScreenOn(true);

? ? }

? ? private Handler handler = new Handler(this);

? ? @Override? ? public void run() {

? ? ? ? while (startDraw) {

? ? ? ? ? ? if (urlPath != null) {

? ? ? ? ? ? ? ? ? ? try {

? ? ? ? ? ? ? ? ? ? ? ? bitmap = BitmapUtils.toBitmap(urlPath, getWidth(), getHeight());

? ? ? ? ? ? ? ? ? ? ? ? if (bitmap == null) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? startDraw = true;

? ? ? ? ? ? ? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? ? ? ? ? ? ? startDraw = false;

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? } catch (Exception e) {

? ? ? ? ? ? ? ? ? ? ? ? Log.d("CustomSurfaceView", "CustomSurfaceView ------- " + e.toString());

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? handler.sendEmptyMessage(1);

? ? ? ? }

? ? }

? ? /*

? ? ? ? * 創(chuàng)建

? ? ? ? */? ?

?@Override? ??

public void surfaceCreated(SurfaceHolder holder) {

? ? ? ? startDraw = true;

? ? ? ? canvas = mSurfaceHolder.lockCanvas();

? ? ? ? canvas.setBitmap(saveBitmap);

? ? ? ? mSurfaceHolder.unlockCanvasAndPost(canvas);

? ? ? ? new Thread(this).start();

? ? }

? ? @Override? ??

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

? ? ? ? super.onMeasure(widthMeasureSpec, heightMeasureSpec);

? ? ? ? viewWidth = getWidth();

? ? ? ? viewHeight = getHeight();

? ? }

? ? @Override? ??

public void surfaceChanged(SurfaceHolder holder, int format, int width,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int height) {

? ? }

? ? /*

? ? * 銷毀

? ? */? ??

@Override? ??

public void surfaceDestroyed(SurfaceHolder holder) {

? ? ? ? startDraw = false;

? ? }

? ? int startX;

? ? int startY;

? ? int stopX;

? ? int stopY;

? ? @Override? ??

public boolean onTouchEvent(MotionEvent event) {

? ? ? ? switch (event.getAction()) {

? ? ? ? ? ? case MotionEvent.ACTION_DOWN:

? ? ? ? ? ? ? ? mPath = new Path();

? ? ? ? ? ? ? ? mpaint = new Paint();

? ? ? ? ? ? ? ? startX = 0;

? ? ? ? ? ? ? ? startY = 0;

? ? ? ? ? ? ? ? startX = (int) event.getX();

? ? ? ? ? ? ? ? startY = (int) event.getY();

? ? ? ? ? ? ? ? mPath.moveTo(startX, startY);

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? case MotionEvent.ACTION_MOVE:

? ? ? ? ? ? ? ? stopX = (int) event.getX();

? ? ? ? ? ? ? ? stopY = (int) event.getY();

? ? ? ? ? ? ? ? if (state == 0) {

? ? ? ? ? ? ? ? ? ? draws();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? case MotionEvent.ACTION_UP:

? ? ? ? ? ? ? ? if (drawPathList.size() + 1 <= 1){

? ? ? ? ? ? ? ? ? ? if (state == 0) {

? ? ? ? ? ? ? ? ? ? ? ? mPath.moveTo(startX, startY);

? ? ? ? ? ? ? ? ? ? ? ? mPath.lineTo(startX, stopY);

? ? ? ? ? ? ? ? ? ? ? ? mPath.lineTo(stopX, stopY);

? ? ? ? ? ? ? ? ? ? ? ? mPath.lineTo(stopX, startY);

? ? ? ? ? ? ? ? ? ? ? ? mPath.lineTo(startX, startY);

? ? ? ? ? ? ? ? ? ? ? ? mPath.close();

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? position.add(union((int) (stopX / scaleX), (int) (stopY / scaleY),

? ? ? ? ? ? ? ? ? ? ? ? (int) (startX / scaleX), (int) (startY / scaleY),

? ? ? ? ? ? ? ? ? ? ? ? (int) (startX / scaleX), (int) (startY / scaleY)));

? ? ? ? ? ? ? ? setPosition(position);

? ? ? ? ? ? ? ? drawPathList.add(new DrawPath(mpaint, mPath));

? ? ? ? ? ? ? ? //? 限制繪制矩形個(gè)數(shù)? ? ? ? ? ? ? ?

?if (drawPathList.size() == 3){?

? ? ? ? ? ? ? ? ? ? drawPathList.remove(drawPathList.size() - 2);

//? ? ? ? ? ? ? ? ? ? drawPathList.add(new DrawPath(mpaint, mPath));? ? ? ? ? ? ? ?

?}

? ? ? ? ? ? ? ? if (position.size() == 3){

? ? ? ? ? ? ? ? ? ? position.remove(position.size() - 2);

//? ? ? ? ? ? ? ? ? ? position.add(union((int) (stopX / scaleX), (int) (stopY / scaleY),

//? ? ? ? ? ? ? ? ? ? ? ? ? ? (int) (startX / scaleX), (int) (startY / scaleY),

//? ? ? ? ? ? ? ? ? ? ? ? ? ? (int) (startX / scaleX), (int) (startY / scaleY)));? ? ? ? ? ? ? ? ? ??

setPosition(position);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? break;

? ? ? ? }

? ? ? ? return true;

? ? }

? ? /**? ? * 判斷四個(gè)頂點(diǎn)的位置,繪制矩形? ?

?* @paramx? ??

?* @paramy? ?

?* @paramleft? ?

?* @paramtop? ?

?* @paramright? ?

?* @parambottom? ??

?* @return

*/? ??

public Postion union(int x, int y, int left, int top, int right, int bottom) {

? ? ? ? int temp = 0;

? ? ? ? if (x < left) {

? ? ? ? ? ? temp = left;

? ? ? ? ? ? left = x;

? ? ? ? ? ? right = temp;

? ? ? ? } else if (x > right) {

? ? ? ? ? ? temp = right;

? ? ? ? ? ? right = x;

? ? ? ? ? ? left = temp;

? ? ? ? }

? ? ? ? if (y < top) {

? ? ? ? ? ? temp = top;

? ? ? ? ? ? top = y;

? ? ? ? ? ? bottom = temp;

? ? ? ? } else if (y > bottom) {

? ? ? ? ? ? temp = bottom;

? ? ? ? ? ? bottom = y;

? ? ? ? ? ? top = temp;

? ? ? ? }

? ? ? ? return new Postion(left, top, right, bottom);

? ? }

? ? /**

? ? * 獲取繪制的四個(gè)點(diǎn)在原圖的位置集合

? ? */? ?

?private List position = new ArrayList<>();

? ? public List getPosition() {

? ? ? ? return position;

? ? }

? ? public void setPosition(List position1) {

? ? ? ? this.position = position1;

? ? }

? ? public void draws() {

? ? ? ? if (bitmap == null) {

? ? ? ? ? ? Toast.makeText(getContext(), "加載圖片失敗", Toast.LENGTH_SHORT).show();

? ? ? ? ? ? Log.e("msg", "加載圖片失敗");

? ? ? ? ? ? return;

? ? ? ? }

? ? ? ? canvas = mSurfaceHolder.lockCanvas();

? ? ? ? Rect rectF = new Rect(0, 0, getWidth(), getHeight());? //w和h分別是屏幕的寬和高,也就是你想讓圖片顯示的寬和高? ? ? ??

scaleX = (float) getWidth() / bitmap.getWidth();

? ? ? ? scaleY = (float) getHeight() / bitmap.getHeight();

? ? ? ? canvas.drawBitmap(bitmap, null, rectF, null);

? ? ? ? mpaint.setStyle(Paint.Style.STROKE);

? ? ? ? mpaint.setAntiAlias(true);

? ? ? ? for (int i = 0; i < drawPathList.size(); i++) {

? ? ? ? ? ? //把path中的路線繪制出來? ? ? ? ? ?

?canvas.drawPath(drawPathList.get(i).path, drawPathList.get(i).paint);

? ? ? ? }

? ? ? ? mpaint.setColor(Color.RED);

? ? ? ? if (state == 0) {

? ? ? ? ? ? mpaint.setColor(Color.RED);

? ? ? ? ? ? mpaint.setStyle(Paint.Style.STROKE);

? ? ? ? ? ? mpaint.setStrokeWidth(StrokeWidth);

? ? ? ? ? ? canvas.drawRect(startX, startY, stopX, stopY, mpaint);

? ? ? ? }

? ? ? ? mSurfaceHolder.unlockCanvasAndPost(canvas);

? ? }

? ? @Override? ??

public boolean handleMessage(Message msg) {

? ? ? ? canvas = mSurfaceHolder.lockCanvas();

? ? ? ? //這里相當(dāng)于是一個(gè)預(yù)覽圖? ? ? ??

Rect rectF = new Rect(0, 0, viewWidth, viewHeight);??

//w和h分別是屏幕的寬和高,也就是你想讓圖片顯示的寬和高? ? ? ?

?if (bitmap!= null&& canvas!= null)

? ? ? ? canvas.drawBitmap(bitmap, null, rectF, null);

? ? ? ? if (canvas!= null)

? ? ? ? mSurfaceHolder.unlockCanvasAndPost(canvas);

? ? ? ? if (bitmap != null) {

? ? ? ? ? ? startDraw = false;

? ? ? ? }

? ? ? ? return false;

? ? }

? ? public classDrawPath{? ? ? ??

public Paint paint;

? ? ? ? public Path path;

? ? ? ? public DrawPath(Paint paint, Path path) {

? ? ? ? ? ? this.paint = paint;

? ? ? ? ? ? this.path = path;

? ? ? ? }

? ? }

? ? /**

? ? * 撤銷上一個(gè)矩形

? ? */? ??

public void revocation() {

? ? ? ? if (drawPathList.size() > 0) {

? ? ? ? ? ? drawPathList.remove(drawPathList.size() - 1);

? ? ? ? ? ? position.remove(position.size() - 1);

? ? ? ? ? ? if (drawPathList.size() == 0){

? ? ? ? ? ? ? ? position = new ArrayList<>();

? ? ? ? ? ? }

? ? ? ? ? ? startX = 0; startY = 0; stopX = 0; stopY = 0;

? ? ? ? ? ? draws();

? ? ? ? }

? ? }

? ? /**

? ? * 位置 Bean

? ? */? ??

public classPostion{? ? ? ??

public int left;

? ? ? ? public int top;

? ? ? ? public int right;

? ? ? ? public int bottom;

? ? ? ? public int getLeft() {

? ? ? ? ? ? return left;

? ? ? ? }

? ? ? ? public int getTop() {

? ? ? ? ? ? return top;

? ? ? ? }

? ? ? ? public int getRight() {

? ? ? ? ? ? return right;

? ? ? ? }

? ? ? ? public int getBottom() {

? ? ? ? ? ? return bottom;

? ? ? ? }

? ? ? ? public Postion(int left, int top, int right, int bottom) {

? ? ? ? ? ? this.left = left;

? ? ? ? ? ? this.top = top;

? ? ? ? ? ? this.right = right;

? ? ? ? ? ? this.bottom = bottom;

? ? ? ? }

? ? }

}

在Activity中對(duì)CustomSurfaceView進(jìn)行實(shí)例化,并傳入圖片,監(jiān)聽按鈕進(jìn)行裁剪和撤銷處理

surfce = new CustomSurfaceView(CropActivity.this, photoPath, false);?

?linear.addView(surfce); //設(shè)置當(dāng)前狀態(tài)為畫矩形

? ? surfce.setState(0);? ??

findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {

? ? ? ? @Override

? ? ? ? public void onClick(View v) {

? ? ? ? ? ? position = new ArrayList<>();? ? ? ? ? ?

?if (bitmap != null) {

? ? ? ? ? ? ? ? position = surfce.getPosition();? ? ? ? ? ? ??

? bitmap1 = null;? ? ? ? ? ? ??

? bitmap2 = null;? ? ? ? ??

? ? ? bitmap1 = Bitmap.createBitmap(bitmap, surfce.getPosition().get(0).getLeft(),

? ? ? ? ? ? ? ? ? ? ? ? surfce.getPosition().get(0).getTop(),

? ? ? ? ? ? ? ? ? ? ? ? surfce.getPosition().get(0).getRight() - surfce.getPosition().get(0).getLeft(),

? ? ? ? ? ? ? ? ? ? ? ? surfce.getPosition().get(0).getBottom() - surfce.getPosition().get(0).getTop());? ? ? ? ? ? ? ?

?bitmap2 = Bitmap.createBitmap(bitmap, surfce.getPosition().get(1).getLeft(),

? ? ? ? ? ? ? ? ? ? ? ? surfce.getPosition().get(1).getTop(),

? ? ? ? ? ? ? ? ? ? ? ? surfce.getPosition().get(1).getRight() - surfce.getPosition().get(1).getLeft(),

? ? ? ? ? ? ? ? ? ? ? ? surfce.getPosition().get(1).getBottom() - surfce.getPosition().get(1).getTop());? ? ? ? ? ??

? ? if (bitmap == null || bitmap1 == null || bitmap2 == null || position.size() != 2) {

? ? ? ? ? ? ? ? ? ? final AlertDialog.Builder builder = new AlertDialog.Builder(CropActivity.this);? ? ? ? ? ? ? ? ? ? builder.setMessage("照片裁剪失敗,請(qǐng)重新裁剪!!")

? ? ? ? ? ? ? ? ? ? ? ? ? ? .setTitle("提示")

? ? ? ? ? ? ? ? ? ? ? ? ? ? .setPositiveButton("返回", null);? ? ? ? ? ? ?

?? } else {

? ? ? ? ? ? ? ? ? ? image01.setImageBitmap(bitmap1);? ? ? ? ? ? ? ??

? ? image02.setImageBitmap(bitmap2);? ? ? ? ??

? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? });? ?

?findViewById(R.id.canle).setOnClickListener(new View.OnClickListener() {

? ? ? ? @Override

? ? ? ? public void onClick(View v) {

? ? ? ? ? ? surfce.revocation(); ? ?//撤銷

? ? }

? ? });

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容