Android中如何实现矩形区域截屏
Android中如何实现矩形区域截屏
这篇文章主要介绍“Android中如何实现矩形区域截屏”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Android中如何实现矩形区域截屏”文章能帮助大家解决问题。
第一步、在屏幕上标识出截图区域
首先确定标识截图区域所需要的功能:
手指拖动形成矩形区域;
可以拖动已经划好的矩形区域进行移动;
可以拖动矩形区域的边框调整大小;
选择完成以后,有“确认”和“取消”功能,“确认”时可以获得选取的区域位置。需要注意的是,按钮的位置应该能够自适应,比如选框几乎占据全屏的情况下,应该把按钮放到选框内部。
最简单的方式就是写一个自定义View,根据touch的位置执行不同的功能即可。实现很简单,只要细心把每一种状态就行,代码请看 Bigbang 项目的MarkSizeView类。
第二步、调用系统接口截屏
截屏必须在Activity中进行,因为需要调用startActivityForResult()。不过也可以把mMediaProjectionManager传到service中进行后续处理。
还要注意的是Activity本身在截屏的时候应该是透明的,不能对要截取得内容有影响。
直接看代码:
publicclassScreenCaptureActivityextendsActivity{privatestaticfinalStringTAG=ScreenCaptureActivity.class.getName();privateMediaProjectionManagermMediaProjectionManager;privateintREQUEST_MEDIA_PROJECTION=1;privateSimpleDateFormatdateFormat;privateStringpathImage;privateWindowManagermWindowManager;privateImageReadermImageReader;privateMediaProjectionmMediaProjection;privateintmResultCode;privateIntentmResultData;privateVirtualDisplaymVirtualDisplay;privateStringstrDate;privateintwindowWidth;privateintwindowHeight;privateStringnameImage;privateintmScreenDensity;@RequiresApi(api=Build.VERSION_CODES.LOLLIPOP)@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);mMediaProjectionManager=(MediaProjectionManager)getApplication().getSystemService(Context.MEDIA_PROJECTION_SERVICE);createVirtualEnvironment();startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(),REQUEST_MEDIA_PROJECTION);}@TargetApi(Build.VERSION_CODES.LOLLIPOP)@OverridepublicvoidonActivityResult(intrequestCode,intresultCode,Intentdata){if(requestCode==REQUEST_MEDIA_PROJECTION){if(resultCode!=Activity.RESULT_OK){return;}elseif(data!=null&&resultCode!=0){mResultCode=resultCode;mResultData=data;startVirtual();newHandler(Looper.getMainLooper()).postDelayed(newRunnable(){@Overridepublicvoidrun(){startCapture();}},100);}}}@RequiresApi(api=Build.VERSION_CODES.KITKAT)privatevoidcreateVirtualEnvironment(){dateFormat=newSimpleDateFormat("yyyy_MM_dd_hh_mm_ss");strDate=dateFormat.format(newDate());pathImage=Environment.getExternalStorageDirectory().getPath()+"/Pictures/";nameImage=pathImage+strDate+".png";mMediaProjectionManager=(MediaProjectionManager)getApplication().getSystemService(Context.MEDIA_PROJECTION_SERVICE);mWindowManager=(WindowManager)getApplication().getSystemService(Context.WINDOW_SERVICE);windowWidth=mWindowManager.getDefaultDisplay().getWidth();windowHeight=mWindowManager.getDefaultDisplay().getHeight();DisplayMetricsmetrics=newDisplayMetrics();mWindowManager.getDefaultDisplay().getMetrics(metrics);mScreenDensity=metrics.densityDpi;mImageReader=ImageReader.newInstance(windowWidth,windowHeight,0x1,2);//ImageFormat.RGB_565Log.i(TAG,"preparedthevirtualenvironment");}@TargetApi(Build.VERSION_CODES.LOLLIPOP)publicvoidstartVirtual(){if(mMediaProjection!=null){Log.i(TAG,"wanttodisplayvirtual");virtualDisplay();}else{Log.i(TAG,"startscreencaptureintent");Log.i(TAG,"wanttobuildmediaprojectionanddisplayvirtual");setUpMediaProjection();virtualDisplay();}}@TargetApi(Build.VERSION_CODES.LOLLIPOP)publicvoidsetUpMediaProjection(){mMediaProjection=mMediaProjectionManager.getMediaProjection(mResultCode,mResultData);Log.i(TAG,"mMediaProjectiondefined");}@TargetApi(Build.VERSION_CODES.LOLLIPOP)privatevoidvirtualDisplay(){mVirtualDisplay=mMediaProjection.createVirtualDisplay("screen-mirror",windowWidth,windowHeight,mScreenDensity,DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,mImageReader.getSurface(),null,null);Log.i(TAG,"virtualdisplayed");}@TargetApi(Build.VERSION_CODES.LOLLIPOP)privatevoidstartCapture(){strDate=dateFormat.format(newjava.util.Date());nameImage=pathImage+strDate+".png";Imageimage=mImageReader.acquireLatestImage();intwidth=image.getWidth();intheight=image.getHeight();finalImage.Plane[]planes=image.getPlanes();finalByteBufferbuffer=planes[0].getBuffer();intpixelStride=planes[0].getPixelStride();introwStride=planes[0].getRowStride();introwPadding=rowStride-pixelStride*width;Bitmapbitmap=Bitmap.createBitmap(width+rowPadding/pixelStride,height,Bitmap.Config.ARGB_8888);bitmap.copyPixelsFromBuffer(buffer);bitmap=Bitmap.createBitmap(bitmap,0,0,width,height);image.close();Log.i(TAG,"imagedatacaptured");//保存截屏结果,如果要裁剪图片,在这里处理bitmapif(bitmap!=null){try{FilefileImage=newFile(nameImage);if(!fileImage.exists()){fileImage.createNewFile();Log.i(TAG,"imagefilecreated");}FileOutputStreamout=newFileOutputStream(fileImage);if(out!=null){bitmap.compress(Bitmap.CompressFormat.PNG,100,out);out.flush();out.close();Intentmedia=newIntent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);UricontentUri=Uri.fromFile(fileImage);media.setData(contentUri);this.sendBroadcast(media);Log.i(TAG,"screenimagesaved");}}catch(FileNotFoundExceptione){e.printStackTrace();}catch(IOExceptione){e.printStackTrace();}}}@TargetApi(Build.VERSION_CODES.LOLLIPOP)privatevoidtearDownMediaProjection(){if(mMediaProjection!=null){mMediaProjection.stop();mMediaProjection=null;}Log.i(TAG,"mMediaProjectionundefined");}}
第三步、对截图进行裁剪
根据***步得到的截图区域mRect对第二步中得到的截屏结果bitmap进行裁剪:
if(mRect!=null){if(mRect.left<0)mRect.left=0;if(mRect.right<0)mRect.right=0;if(mRect.top<0)mRect.top=0;if(mRect.bottom<0)mRect.bottom=0;intcut_width=Math.abs(mRect.left-mRect.right);intcut_height=Math.abs(mRect.top-mRect.bottom);if(cut_width>0&&cut_height>0){BitmapcutBitmap=Bitmap.createBitmap(bitmap,mRect.left,mRect.top,cut_width,cut_height);}
需要注意的是,在调用系统截屏功能的时候,如果手机有NavigationBar(虚拟导航栏),windowHeight的取值就是不包括NavigationBar的高度的,如果不进行调整,就会导致截屏被压缩。如何获取屏幕的真实高度,可以参考 Android如何判断NavigationBar是否显示(获取屏幕真实的高度) 。
而且NavigationBar还会导致截屏的结果出现边框,边框的颜色是透明的,原因是第二步代码中的rowPadding!=0,截屏如下图所示:
带NavigationBar使用系统截图的结果
那么如果我们想要对截图的结果进行保存或者裁剪,就必须要去除边框,找出真正的内容区域,也就是在***个不透明的像素和***一个不透明像素之间的内容,然后才能对得到的区域进行第三步的裁剪,代码如下:
int[]pixel=newint[width];bitmap.getPixels(pixel,0,width,0,0,width,1);intleftPadding=0;intrightPadding=width;for(inti=0;i<pixel.length;i++){if(pixel[i]!=0){leftPadding=i;break;}}for(inti=pixel.length-1;i>=0;i--){if(pixel[i]!=0){rightPadding=i;break;}}bitmap=Bitmap.createBitmap(bitmap,leftPadding,0,rightPadding-leftPadding,height);
处理后的截图如下:
取得截图结果的内容部分
你可能会觉得既然是rowPadding!=0导致出现边框,而且边框只在右边,为什么不直接把右边rowPadding宽度的内容截掉呢?其实是因为如果不调整windowHeight,就会在左边也产生框,所以才用了上面的方法。
关于“Android中如何实现矩形区域截屏”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注恰卡编程网行业资讯频道,小编每天都会为大家更新不同的知识点。
推荐阅读
-
android(如何快速开发框架 小米note开发版MIUI,安卓6.0,怎么安装Xposed框架)
稳定版,你必须先根除。你上网搜索安卓可以叫别人s框架,对方可以把框架做成jar包,把这个jar包加载到项目目录的libs文件中使...
-
android(studio 虚拟机启动不了 android studio可以当模拟器用吗)
androidstudio可以当模拟器用吗?AmdCUP引导模拟器有点复杂。雷电模拟器上的抖音怎么登录不上?不是,闪电模拟调用...
-
从实践中学习手机抓包与数据分析(android 手机抓包app)
android手机抓包app?netcapture抓包精灵app(手机抓包工具)又名sslcapture,是什么专业的安卓手机抓...
-
android(studio全局搜索 android studio怎么看app界面)
androidstudio怎么看app界面?在设备桌面点击运用直接进入到App界面,就也可以参与其他你的操作了。android-...
-
怎么把android框架源代码拉到本地(android studio如何运行别人的源代码)
androidstudio如何运行别人的源代码?androidstudio点击刚建在列表中你选择导入module,导入即可在用...
-
android(studio2022年使用教程 怎么安装Android studio详细教程)
怎么安装Androidstudio详细教程?androidstudio中haxm直接安装的方法追加:1、简单的方法打开Andr...
-
怎么使用Android基准配置文件Baseline Profile方案提升启动速度
-
HTML5如何实现禁止android视频另存为
-
学java好还是学php好?
-
Android如何实现多点触控功能