站群cms系统,区块链,网页制作与设计书籍心得体会,中国建筑材料价格网对屏幕进行截屏并裁剪有两种方式#xff1a;早截图和晚截图。早截图#xff0c;就是先截取全屏#xff0c;再让用户对截取到的图片进行修改;与之相对的#xff0c;晚截图#xff0c;就是先让用户在屏幕上划好区域#xff0c;再进行截图和裁剪。其实两者并没有什么太大的区…对屏幕进行截屏并裁剪有两种方式早截图和晚截图。早截图就是先截取全屏再让用户对截取到的图片进行修改;与之相对的晚截图就是先让用户在屏幕上划好区域再进行截图和裁剪。其实两者并没有什么太大的区别这篇就说说怎么实现晚截图。晚截图可以分成三步在屏幕上标出截图的矩形区域调用系统接口截屏对截图进行裁剪效果图如下矩形区域截屏***步、在屏幕上标识出截图区域首先确定标识截图区域所需要的功能手指拖动形成矩形区域;可以拖动已经划好的矩形区域进行移动;可以拖动矩形区域的边框调整大小;选择完成以后有“确认”和“取消”功能“确认”时可以获得选取的区域位置。需要注意的是按钮的位置应该能够自适应比如选框几乎占据全屏的情况下应该把按钮放到选框内部。最简单的方式就是写一个自定义View根据touch的位置执行不同的功能即可。实现很简单只要细心把每一种状态就行代码请看 Bigbang 项目的MarkSizeView类。第二步、调用系统接口截屏截屏必须在Activity中进行因为需要调用startActivityForResult()。不过也可以把mMediaProjectionManager传到service中进行后续处理。还要注意的是Activity本身在截屏的时候应该是透明的不能对要截取得内容有影响。直接看代码publicclass ScreenCaptureActivity extends Activity { privatestaticfinal String TAG ScreenCaptureActivity.class.getName(); private MediaProjectionManager mMediaProjectionManager; privateintREQUEST_MEDIA_PROJECTION 1; private SimpleDateFormat dateFormat; private String pathImage; private WindowManager mWindowManager; private ImageReader mImageReader; private MediaProjection mMediaProjection; privateintmResultCode; private Intent mResultData; private VirtualDisplay mVirtualDisplay; private String strDate; privateintwindowWidth; privateintwindowHeight; private String nameImage; privateintmScreenDensity; RequiresApi(api Build.VERSION_CODES.LOLLIPOP) Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);mMediaProjectionManager (MediaProjectionManager) getApplication().getSystemService(Context.MEDIA_PROJECTION_SERVICE);createVirtualEnvironment();startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);} TargetApi(Build.VERSION_CODES.LOLLIPOP) Overridepublicvoid onActivityResult(intrequestCode,intresultCode, Intent data) { if (requestCode REQUEST_MEDIA_PROJECTION) { if (resultCode ! Activity.RESULT_OK) {return;} elseif (data !null resultCode ! 0) {mResultCode resultCode;mResultData data;startVirtual(); new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { Overridepublicvoid run() {startCapture();}},100);}}} RequiresApi(api Build.VERSION_CODES.KITKAT) private void createVirtualEnvironment() {dateFormat new SimpleDateFormat(yyyy_MM_dd_hh_mm_ss);strDate dateFormat.format(new Date());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();DisplayMetrics metrics new DisplayMetrics();mWindowManager.getDefaultDisplay().getMetrics(metrics);mScreenDensity metrics.densityDpi;mImageReader ImageReader.newInstance(windowWidth, windowHeight, 0x1, 2); //ImageFormat.RGB_565Log.i(TAG, prepared the virtual environment);} TargetApi(Build.VERSION_CODES.LOLLIPOP) publicvoid startVirtual() { if (mMediaProjection !null) {Log.i(TAG, want to display virtual);virtualDisplay();} else{Log.i(TAG, start screen capture intent);Log.i(TAG, want to build mediaprojection and display virtual);setUpMediaProjection();virtualDisplay();}} TargetApi(Build.VERSION_CODES.LOLLIPOP) publicvoid setUpMediaProjection() {mMediaProjection mMediaProjectionManager.getMediaProjection(mResultCode, mResultData);Log.i(TAG, mMediaProjection defined);} TargetApi(Build.VERSION_CODES.LOLLIPOP) private void virtualDisplay() {mVirtualDisplay mMediaProjection.createVirtualDisplay(screen-mirror,windowWidth, windowHeight, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,mImageReader.getSurface(), null,null);Log.i(TAG, virtual displayed);} TargetApi(Build.VERSION_CODES.LOLLIPOP) private void startCapture() {strDate dateFormat.format(new java.util.Date());nameImage pathImage strDate .png;Image image mImageReader.acquireLatestImage(); intwidth image.getWidth();intheight image.getHeight(); final Image.Plane[] planes image.getPlanes(); final ByteBuffer buffer planes[0].getBuffer();intpixelStride planes[0].getPixelStride();introwStride planes[0].getRowStride();introwPadding rowStride - pixelStride * width;Bitmap bitmap 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, image data captured); //保存截屏结果如果要裁剪图片在这里处理bitmapif (bitmap ! null) { try {File fileImage new File(nameImage); if (!fileImage.exists()) {fileImage.createNewFile();Log.i(TAG, image file created);}FileOutputStream out new FileOutputStream(fileImage); if (out!null) {bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);out.flush();out.close();Intent media new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);Uri contentUri Uri.fromFile(fileImage);media.setData(contentUri); this.sendBroadcast(media);Log.i(TAG, screen image saved);}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}} TargetApi(Build.VERSION_CODES.LOLLIPOP) private void tearDownMediaProjection() { if (mMediaProjection ! null) {mMediaProjection.stop();mMediaProjection null;}Log.i(TAG, mMediaProjection undefined);}}第三步、对截图进行裁剪根据***步得到的截图区域mRect对第二步中得到的截屏结果bitmap进行裁剪if (mRect !null) { if (mRect.leftmRect.left 0; if (mRect.rightmRect.right 0; if (mRect.topmRect.top 0; if (mRect.bottom 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) {Bitmap cutBitmap Bitmap.createBitmap(bitmap, mRect.left, mRect.top, cut_width, cut_height);}需要注意的是在调用系统截屏功能的时候如果手机有NavigationBar(虚拟导航栏)windowHeight的取值就是不包括NavigationBar的高度的如果不进行调整就会导致截屏被压缩。如何获取屏幕的真实高度可以参考 Android如何判断NavigationBar是否显示(获取屏幕真实的高度) 。而且NavigationBar还会导致截屏的结果出现边框边框的颜色是透明的原因是第二步代码中的rowPadding!0截屏如下图所示带NavigationBar使用系统截图的结果那么如果我们想要对截图的结果进行保存或者裁剪就必须要去除边框找出真正的内容区域也就是在***个不透明的像素和***一个不透明像素之间的内容然后才能对得到的区域进行第三步的裁剪代码如下int[] pixelnewint[width];bitmap.getPixels(pixel,0,width ,0,0,width,1);intleftPadding0;intrightPaddingwidth;for(inti0;ileftPaddingi; break;}}for(intipixel.length-1;i0;i--){ if (pixel[i]!0){rightPaddingi; break;}}bitmapBitmap.createBitmap(bitmap,leftPadding, 0, rightPadding-leftPadding, height);处理后的截图如下取得截图结果的内容部分你可能会觉得既然是rowPadding!0导致出现边框而且边框只在右边为什么不直接把右边rowPadding宽度的内容截掉呢?其实是因为如果不调整windowHeight就会在左边也产生框所以才用了上面的方法。完整代码可以参考 Bigbang 项目的MarkSizeView类、ScreenCaptureActivity类和ScreenCapture类。【编辑推荐】【责任编辑枯木 TEL(010)68476606】点赞 0