Android 仿PC端QQ自由截圖,可支援一次截多個區域
阿新 • • 發佈:2019-01-06
仿PC端QQ截圖,可任意截圖,這裡只做了矩形這一種形狀,可同時支援擷取多個區域,支援撤銷上次截圖,重新擷取。
實現原理:
自定義SurfaceView,在SurfaceView上繪製具有一個可拉伸,移動的矩形框,當點選截圖按鈕後,計算矩形框的座標值及原圖尺寸,通過比例將矩形框的座標值轉化到原圖中相對應的座標,然後進行裁剪。
這裡矩形框目前只設置了兩個。
**
**
實現程式碼:
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<DrawPath> 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);
}
}
/*
* 建立
*/
@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));
// 限制繪製矩形個數
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;
}
/**
* 判斷四個頂點的位置,繪製矩形
* @param x
* @param y
* @param left
* @param top
* @param right
* @param bottom
* @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);
}
/**
* 獲取繪製的四個點在原圖的位置集合
*/
private List<Postion> position = new ArrayList<>();
public List<Postion> getPosition() {
return position;
}
public void setPosition(List<Postion> 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();
//這裡相當於是一個預覽圖
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 class DrawPath {
public Paint paint;
public Path path;
public DrawPath(Paint paint, Path path) {
this.paint = paint;
this.path = path;
}
}
/**
* 撤銷上一個矩形
*/
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 class Postion{
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中對CustomSurfaceView進行例項化,並傳入圖片,監聽按鈕進行裁剪和撤銷處理
surfce = new CustomSurfaceView(CropActivity.this, photoPath, false);
linear.addView(surfce);
//設定當前狀態為畫矩形
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("照片裁剪失敗,請重新裁剪!!")
.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();
}
});