[文章] Android View 截图 转bitmap 然后保存成图片 View 上面弹框什么的不会被 截取到 废话不多说直接上代码fungetBitmapFromView(window:Window,targetView:View,width:Int?=null):Bitmap{valfinalWidth=width?:targetView.widthif(finalWidth<=0){//Log.w(TAG,"finalWidth=$finalWidth")throwIllegalArgumentException("宽度小于等于0,finalWidth=$finalWidth")}//这里做了一个安卓版本判断returnif(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){copyPixelFromView(window,targetView,finalWidth)}else{convertViewToBitmap(targetView,finalWidth)}}/**/***Android26(O)(8.0)以下的版本,使用此方法,某些情况下颜色有偏差,已经View采集不全,比如Android14上摄像头内容未采集到*如果采用drawingCache.copy宽高未生效,还是View原始的宽高,要生效需采用Canvas方式*drawingCache.copy耗时:6-9ms,Canvas方式还更快,所以目前改为Canvas实现*/*/@ThrowsfunconvertViewToBitmap(targetView:View,width:Int):Bitmap{//优化宽高valrecordWidth=if(width%2!=0){width-1}else{width}varrecordHeight=if(recordWidth==targetView.width){//宽度不变,则高度也不变targetView.height}else{(targetView.height*(recordWidth.toFloat()/targetView.width)).toInt()}if(recordHeight%2!=0){recordHeight-=1}valbitmap=Bitmap.createBitmap(recordWidth,recordHeight,mBitmapConfig)valcanvas=Canvas(bitmap)//保存当前状态,目前只改变一次,多余//valsaveCount=canvas.save()//缩放Canvas来匹配目标Bitmapcanvas.scale(recordWidth.toFloat()/targetView.width,recordHeight.toFloat()/targetView.height)//将View绘制到Canvas上targetView.draw(canvas)//恢复Canvas状态//canvas.restoreToCount(saveCount)returnbitmap}/***@paramwidth指定宽度,等比例缩放高度*@paramtargetView只是为了算坐标,没其他用*/@RequiresApi(Build.VERSION_CODES.O)@ThrowsfuncopyPixelFromView(window:Window,targetView:View,width:Int):Bitmap{//Log.i(TAG,"currentThread:${Thread.currentThread().name}")//优化宽高valrecordWidth=if(width%2!=0){width-1}else{width}varrecordHeight=if(recordWidth==targetView.width){//宽度不变,则高度也不变targetView.height}else{(targetView.height*(recordWidth.toFloat()/targetView.width)).toInt()}if(recordHeight%2!=0){recordHeight-=1}//黑屏//valbitmap=Bitmap.createBitmap(recordWidth,recordHeight,Bitmap.Config.RGB_565)//准备一个bitmap对象,用来将copy出来的区域绘制到此对象中,view应该是没有alpha的valbitmap=Bitmap.createBitmap(recordWidth,recordHeight,mBitmapConfig)//获取view在Window中的left-top顶点位置,基本上取的当前的window,且录的都是全部,所以都是[0,0]vallocation=IntArray(2)targetView.getLocationInWindow(location)varisSuccessful=false//请求转换//valstart=System.currentTimeMillis()if(!window.isActive){returnbitmap}//valstart=System.currentTimeMillis()//vallatch=CountDownLatch(1)valfuture=CompletableFuture<Boolean>()try{PixelCopy.request(window,//截图区域的取值,左上右下Rect(location[0],location[1],location[0]+targetView.width,location[1]+targetView.height),bitmap,{copyResult->//走完外面才有回调,问题不大,当然最稳妥是回调,但是回调不能同步,得加协程//Log.i(TAG,"回调内isSuccessful=${copyResult==PixelCopy.SUCCESS},耗时=${System.currentTimeMillis()-start}ms")//isSuccessful=copyResult==PixelCopy.SUCCESS//latch.countDown()future.complete(copyResult==PixelCopy.SUCCESS)},mMainHandler)//latch.await(100,TimeUnit.MILLISECONDS)isSuccessful=future.get(100,TimeUnit.MILLISECONDS)}catch(e:Exception){e.printStackTrace()}returnbitmap}调用方式returnRecordViewUtil.getBitmapFromView(window,view,view.width)}2.bitmap转保存成图片funaddPhoto(bitmap:Bitmap){viewModelScope.launch(Dispatchers.Main){valawa=viewModelScope.async(Dispatchers.IO){valname="${System.currentTimeMillis()}.png"//App.install.cacheDir.absolutePath是你自定义的地址valfilePath="${App.install.cacheDir.absolutePath}/image/${name}"BitmapUtil.saveBitToPath(bitmap,filePath)bitmap.recycle()return@asyncDBUtil.getInstall(App.install).addVideoPhoto(VideoPhoto(name,0,filePath,System.currentTimeMillis()))}valid=awa.await()}}```language/**保存文件的方法**/funsaveBitToPath(bit:Bitmap,filePath:String){valfile=File(filePath)file.parentFile?.let{if(!it.exists())it.mkdirs()}if(!file.exists()){file.createNewFile()}valbitData=bitToByteArray(bit)valoutputStream=FileOutputStream(file)outputStream.write(bitData)outputStream.flush()outputStream.close()}最后addPhoto(viewScreenshotBit(window,view))窗口和需要截图的View最后查看保存的图片然后我想说的是现在ai很火大家有问题就会直接问gptdk等还是希望大家问ai的同时自己的大脑也思考一下为什么要这样写不然只做一个只会问ai的人自己本身技术不会有提升。