Android實(shí)現(xiàn)bitmap指定區(qū)域滑動(dòng)截取功能
突然不知道什么心態(tài),說要做這個(gè),網(wǎng)上找了半天沒找到合適的,就自己做了一個(gè)。
先上效果圖:

透明區(qū)域?yàn)閷⒁厝〉膮^(qū)域,其他陰影部位為舍棄區(qū)域
圖片資源我寫死儲(chǔ)存在了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="選擇要截取區(qū)域"/>
</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,以及滑動(dòng)截圖,其中Dot類用來儲(chǔ)存坐標(biāo)點(diǎn)的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進(jìn)行變形,使其鋪滿屏幕
*
*/
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);
}
/**
* 畫出截圖區(qū)域
*
* @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);
}
/**
* 獲取截圖區(qū)域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;
}
/**
* 獲取截圖區(qū)域?qū)挾?
*
* @return
*/
private int getOutWidth() {
return (int) (rightBottomDot.getX() - leftTopDot.getX());
}
/**
* 獲取截圖區(qū)域高度
*
* @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中完成對(duì)點(diǎn)擊滑動(dòng)的監(jiān)控,通過坐標(biāo)點(diǎn)的方式獲得需要繪制的矩形位置和形狀。
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,"請(qǐng)選擇截取區(qū)域",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();
}
}
運(yùn)用了單例模式用來存儲(chǔ)截取出來的bitmap,方便跳轉(zhuǎn)時(shí)調(diào)用,不需要自己再寫類,點(diǎn)擊確定后,會(huì)將區(qū)域中的bitmap提取并存儲(chǔ)在單例中,在下一個(gè)頁面再調(diào)用。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android Bitmap的截取及狀態(tài)欄的隱藏和顯示功能
- android 手機(jī)截取長屏實(shí)例代碼
- 解析Android截取手機(jī)屏幕兩種實(shí)現(xiàn)方案
- Android實(shí)現(xiàn)拍照截取和相冊(cè)圖片截取
- Android個(gè)人中心的頭像上傳,圖片編碼及截取實(shí)例
- Android 仿QQ頭像自定義截取功能
- Android開發(fā)獲取短信的內(nèi)容并截取短信
- Android中截取當(dāng)前屏幕圖片的實(shí)例代碼
- Android截取視頻幀并轉(zhuǎn)化為Bitmap示例
- Android截取指定View為圖片的實(shí)現(xiàn)方法
相關(guān)文章
Android 基于agora 開發(fā)視頻會(huì)議的代碼
這篇文章主要介紹了Android 基于agora 開發(fā)視頻會(huì)議,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01
Android平臺(tái)預(yù)置GMS包后關(guān)機(jī)鬧鐘失效問題及解決方法
這篇文章主要介紹了Android平臺(tái)預(yù)置GMS包后,關(guān)機(jī)鬧鐘失效,本文給大家分享問題原因及解決方法,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09
Android中模仿抖音加載框之兩顆小球轉(zhuǎn)動(dòng)效果
這篇文章主要介紹了Android仿抖音加載框之兩顆小球轉(zhuǎn)動(dòng)控件,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-09-09
解決Android Studio sdk emulator directory is missing問題
這篇文章主要介紹了解決Android Studio sdk emulator directory is missing問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
Android Studio真機(jī)無線連接USB設(shè)備調(diào)試運(yùn)行詳解流程
你在Android Studio寫app時(shí)是否也有想過如果可以不用數(shù)據(jù)線連接手機(jī)調(diào)試運(yùn)行就好了?如果需要取出數(shù)據(jù)線插接的話我肯定是嫌麻煩的,但是模擬器有時(shí)候需要測試一些需要硬件支持的功能時(shí)又不管用,所以最好的測試還是在真機(jī)上,本篇教你扔掉數(shù)據(jù)線來無線調(diào)試2021-11-11
如何使用Mock修改Android設(shè)備上的features
這篇文章主要介紹了如何使用Mock修改Android設(shè)備上的features,想了解Mock的同學(xué)可以參考下2021-04-04
Android使用GestureOverlayView控件實(shí)現(xiàn)手勢識(shí)別
這篇文章主要為大家詳細(xì)介紹了Android使用GestureOverlayView控件實(shí)現(xiàn)手勢識(shí)別,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04

