Android实现bitmap指定区域滑动截取功能
时间:2021-02-09 14:33:44|栏目:Android代码|点击: 次
突然不知道什么心态,说要做这个,网上找了半天没找到合适的,就自己做了一个。
先上效果图:
透明区域为将要截取的区域,其他阴影部位为舍弃区域
图片资源我写死储存在了raw中,有需要可以自己写获取bitmap。
界面layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.admin.myapplication.MainActivity"> <com.admin.myapplication.ScreenShotView android:id="@+id/screenShotView" android:layout_width="match_parent" android:layout_height="match_parent"/> <LinearLayout android:id="@+id/title" android:layout_width="match_parent" android:layout_height="30dp" android:background="#000000"> <TextView android:layout_width="match_parent" android:layout_height="20dp" android:layout_gravity="center" android:gravity="center" android:text="选择要截取区域"/> </LinearLayout> <LinearLayout android:id="@+id/bottom" android:layout_width="match_parent" android:layout_height="70dp" android:layout_alignParentBottom="true" android:background="#000000" android:orientation="horizontal"> <TextView android:id="@+id/cancel_btn" android:text="取消" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:layout_gravity="center_vertical" android:gravity="center"/> <TextView android:id="@+id/certain_btn" android:text="确定" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:layout_gravity="center_vertical" android:gravity="center"/> <TextView android:id="@+id/restart_btn" android:text="重试" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:layout_gravity="center_vertical" android:gravity="center"/> </LinearLayout> </RelativeLayout>
ScreenShotView为自定义View用来显示bitmap,以及滑动截图,其中Dot类用来储存坐标点的x,y值。
public class ScreenShotView extends View { private Dot startDot; private Dot endDot; private Bitmap mBitmap; private Bitmap ocrBitmap; private int screenHeight; private int screenWidth; private Dot leftTopDot; private Dot rightBottomDot; private Paint paintShadow; int shadow = 0xaa000000; int clear = 0x0000000; public ScreenShotView(Context context) { super(context); startDot = new Dot(); endDot = new Dot(); leftTopDot = new Dot(); rightBottomDot = new Dot(); } public ScreenShotView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); startDot = new Dot(); endDot = new Dot(); leftTopDot = new Dot(); rightBottomDot = new Dot(); } public ScreenShotView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); startDot = new Dot(); endDot = new Dot(); leftTopDot = new Dot(); rightBottomDot = new Dot(); } public void setBitmap(Bitmap bitmap, int screenHeight, int screenWidth) { mBitmap = bitmap; this.screenHeight = screenHeight; this.screenWidth = screenWidth; changeBitmapSize(); invalidate(); } public void restart(){ startDot = new Dot(); endDot = new Dot(); leftTopDot = new Dot(); rightBottomDot = new Dot(); invalidate(); } /** *将将要显示的bitmap进行变形,使其铺满屏幕 * */ private void changeBitmapSize() { int width = mBitmap.getWidth(); int height = mBitmap.getHeight(); float scaleWidth = ((float) screenWidth) / width; float scaleHeight = ((float) screenHeight) / height; Matrix matrix = new Matrix(); matrix.postScale(scaleWidth, scaleHeight); mBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height, matrix, true); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); getLeftTopDot(); getRightBottomDot(); drawBitmap(canvas); drawArea(canvas); drawShadowTop(canvas); drawShadowLeft(canvas); drawShadowRight(canvas); drawShadowBottom(canvas); } /** *绘制阴影 * */ private void drawShadowBottom(Canvas canvas) { paintShadow = new Paint(); paintShadow.setColor(shadow); canvas.drawRect(0, rightBottomDot.getY(), screenWidth, screenHeight, paintShadow); } private void drawShadowRight(Canvas canvas) { paintShadow = new Paint(); paintShadow.setColor(shadow); canvas.drawRect(rightBottomDot.getX(), leftTopDot.getY(), screenWidth, rightBottomDot.getY(), paintShadow); } private void drawShadowLeft(Canvas canvas) { paintShadow = new Paint(); paintShadow.setColor(shadow); canvas.drawRect(0, leftTopDot.getY(), leftTopDot.getX(), rightBottomDot.getY(), paintShadow); } private void drawShadowTop(Canvas canvas) { paintShadow = new Paint(); paintShadow.setColor(shadow); canvas.drawRect(0, 0, screenWidth, leftTopDot.getY(), paintShadow); } private void drawBitmap(Canvas canvas) { Paint paint = new Paint(); canvas.drawBitmap(mBitmap, 0, 0, paint); } /** * 画出截图区域 * * @param canvas */ private void drawArea(Canvas canvas) { Paint paint = new Paint(); paint.setColor(clear); canvas.drawRect(leftTopDot.getX(), leftTopDot.getY(), rightBottomDot.getX(), rightBottomDot.getY(), paint); } /** * 获取截图区域bitmap * * @return 截图 */ public Bitmap getBitmap() { if (mBitmap != null) { getLeftTopDot(); getRightBottomDot(); if (getBitmapOutWidth() > 0 && getBitmapOutHeight() > 0) { if(leftTopDot.getY()<0){ leftTopDot.setY(0); } ocrBitmap = Bitmap.createBitmap(mBitmap, (int) leftTopDot.getX(), (int) leftTopDot.getY(), getBitmapOutWidth(), getBitmapOutHeight()); } } return ocrBitmap; } /** * 获取截图区域宽度 * * @return */ private int getOutWidth() { return (int) (rightBottomDot.getX() - leftTopDot.getX()); } /** * 获取截图区域高度 * * @return */ private int getOutHeight() { return (int) (rightBottomDot.getY() - leftTopDot.getY()); } private int getBitmapOutWidth() { int bitmapOutWidth; int scale = getOutWidth() * mBitmap.getWidth(); bitmapOutWidth = scale / screenWidth; return bitmapOutWidth; } private int getBitmapOutHeight() { int bitmapOutHeight; int scale = getOutHeight() * mBitmap.getHeight(); bitmapOutHeight = scale / screenHeight; return bitmapOutHeight; } private void getLeftTopDot() { if (endDot.getX() > startDot.getX()) { leftTopDot.setX(startDot.getX()); } else { leftTopDot.setX(endDot.getX()); } if (endDot.getY() > startDot.getY()) { leftTopDot.setY(startDot.getY()); } else { leftTopDot.setY(endDot.getY()); } } private void getRightBottomDot() { if (startDot.getX() > endDot.getX()) { rightBottomDot.setX(startDot.getX()); } else { rightBottomDot.setX(endDot.getX()); } if (startDot.getY() > endDot.getY()) { rightBottomDot.setY(startDot.getY()); } else { rightBottomDot.setY(endDot.getY()); } } public Dot getStartDot() { return startDot; } public void setStartDot(Dot startDot) { this.startDot = startDot; } public Dot getEndDot() { return endDot; } public void setEndDot(Dot endDot) { this.endDot = endDot; } }
MainActivity中完成对点击滑动的监控,通过坐标点的方式获得需要绘制的矩形位置和形状。
public class MainActivity extends AppCompatActivity implements View.OnTouchListener, View.OnClickListener { private ScreenShotView screenShotView; private Bitmap bmp; private Bitmap ocrBitmap; private TextView certainBtn; private TextView cancelBtn; private TextView restartBtn; private int screenWidth; private int screenHeight; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); screenShotView = (ScreenShotView) findViewById(R.id.screenShotView); cancelBtn = (TextView) findViewById(R.id.cancel_btn); cancelBtn.setOnClickListener(this); certainBtn = (TextView) findViewById(R.id.certain_btn); certainBtn.setOnClickListener(this); restartBtn = (TextView)findViewById(R.id.restart_btn); restartBtn.setOnClickListener(this); DisplayMetrics dm = new DisplayMetrics(); //获取屏幕信息 getWindowManager().getDefaultDisplay().getMetrics(dm); screenWidth = dm.widthPixels; screenHeight = dm.heightPixels; Resources r = this.getResources(); InputStream is = r.openRawResource(R.raw.bg); BitmapDrawable bmpDraw = new BitmapDrawable(is); bmp = bmpDraw.getBitmap(); screenShotView.setBitmap(bmp, screenHeight, screenWidth); screenShotView.setOnTouchListener(this); } @Override public boolean onTouch(View view, MotionEvent motionEvent) { switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: screenShotView.setStartDot(new Dot(motionEvent.getX(), motionEvent.getY())); break; case MotionEvent.ACTION_MOVE: screenShotView.setEndDot(new Dot(motionEvent.getX(), motionEvent.getY())); screenShotView.setBitmap(bmp, screenHeight, screenWidth); break; case MotionEvent.ACTION_UP: ocrBitmap = screenShotView.getBitmap(); break; } return true; } @Override public void onClick(View view) { switch (view.getId()) { case R.id.cancel_btn: finish(); break; case R.id.certain_btn: if (ocrBitmap != null) { BitmapUtil.getInstance().setImageBitmap(ocrBitmap); Intent intent = new Intent(MainActivity.this, Main2Activity.class); startActivity(intent); }else{ Toast.makeText(MainActivity.this,"请选择截取区域",Toast.LENGTH_SHORT).show(); } break; case R.id.restart_btn: screenShotView.restart(); break; } } @Override protected void onResume() { super.onResume(); screenShotView.restart(); } @Override protected void onRestart() { super.onRestart(); screenShotView.restart(); } }
运用了单例模式用来存储截取出来的bitmap,方便跳转时调用,不需要自己再写类,点击确定后,会将区域中的bitmap提取并存储在单例中,在下一个页面再调用。