截屏相关
来源:互联网 发布:db2创建数据库 编辑:程序博客网 时间:2024/06/04 00:21
前段时间在做一个截屏分享的功能,所截取的内容包括一个surfaceView+MediaPlayer的视频,虽然最终实现了该功能,但是确实也走了很多弯路,当时本想总结一下的,但后来一直拖着没弄。最近又涉及到包含listView(要截取listView全部内容,包括屏幕以外的部分)截屏,弄完了就在此记录一下方便以后查看,免得过段时间忘了,又得到处找。
surfaceView截屏思路:
1.、先截取整个静态屏幕(screenBitmap)
2、获取当前的视频帧图片(vedioBitmap)
3、将获取帧图片vedioBitmap绘制在screenBitmap的黑色区域
首先截取静态屏幕,代码如下
<span style="white-space:pre"></span>public static Bitmap takeScreenShot(Activity activity) {// View是你需要截图的ViewView view = activity.getWindow().getDecorView();view.setDrawingCacheEnabled(true);view.buildDrawingCache();Bitmap b1 = view.getDrawingCache();// 获取状态栏高度Rect frame = new Rect();activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);int statusBarHeight = frame.top;System.out.println(statusBarHeight);// 获取屏幕长和高int width = activity.getWindowManager().getDefaultDisplay().getWidth();int height = activity.getWindowManager().getDefaultDisplay().getHeight();// 去掉标题栏// Bitmap b = Bitmap.createBitmap(b1, 0, 25, 320, 455);Bitmap b = Bitmap.createBitmap(b1, 0, statusBarHeight, width, height- statusBarHeight);view.destroyDrawingCache();savePic(b, "/sdcard/screen_test.png");return b;}
这个方法截取静态屏幕是没问题的,但视频部分截出来的趋势黑色一片,根本不能看,主要是surfaceView的实现原理,如下:
SurfaceView通常有两个缓冲区(buffer), 一个front buffer,一个back buffer。而back buffer就是Canvas对应的bitmap。每当frong buffer显示时,back buffer就迅速的绘制,然后front buffer迅速将当前的back buffer显示给用户。由于速度十分快,所以便形成了动画效果。View是在UI的主线程中更新画面,而SurfaceView是在一个新线程中更新画面。这就需要你new一个新线程,在新线程里面进行绘画的工作。 SurfaceView通过SurfaceHolder对象将back buffer画好的内容更新到front buffer。 这也就是为什么我们在使用SurfaceView时需要将canvas进行锁定。 那么说了这么多,SurfaceView和普通View有什么区别? (静态与动态的区别)
主要在于普通View内容draw之后,是静态的,我们不调用invalidate它就放在那, 拿到了Bitmap之后,我们可以获取到里面的内容。但是SurfaceView不同,我们无法拿到back buffer里面的bitmap。所以我们以往常用的截屏方案就不能够达到截下SurfaceView的效果。
获取当前的视频帧图片,代码如下:
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)private Bitmap createVideoThumbnail(String url, int width, int height) { Bitmap bitmap = null; MediaMetadataRetriever retriever = new MediaMetadataRetriever(); int kind = MediaStore.Video.Thumbnails.MINI_KIND; try { if (Build.VERSION.SDK_INT >= 14) { retriever.setDataSource(url, new HashMap<String, String>()); } else { retriever.setDataSource(url); } bitmap = retriever.getFrameAtTime(); } catch (IllegalArgumentException ex) { // Assume this is a corrupt video file } catch (RuntimeException ex) { // Assume this is a corrupt video file. } finally { try { retriever.release(); } catch (RuntimeException ex) { // Ignore failures while cleaning up. } } if (kind == Images.Thumbnails.MICRO_KIND && bitmap != null) { bitmap = ThumbnailUtils.extractThumbnail(bitmap, width, height, ThumbnailUtils.OPTIONS_RECYCLE_INPUT); } return bitmap; }最后根据自己的逻辑(计算好位置、图片的宽高等等),以获取的静态屏幕图片为画布,将获取的帧图片绘制在黑色区域,即可。
查看的关于截屏的文章如下:
http://blog.csdn.net/bboyfeiyu/article/details/12712141
http://blog.csdn.net/hk_256/article/details/7306590
http://blog.csdn.net/yilip/article/details/7745584
http://blog.csdn.net/linyukun6422/article/details/43191333
http://huobengluantiao8.iteye.com/blog/1578117
http://www.tuicool.com/articles/uqmUFfY
http://blog.csdn.net/woshinia/article/details/11520403
listView截屏思路(gridView类似):
listView的截屏就比较简单了,主要是把每个item的view转换为bitmap,然后注意绘制在适当的位置就ok了。参考http://www.darcye.com/article/84263064
<span style="white-space:pre"></span>public static Bitmap createBitmap(ListView listView, Context context) {int width, rootHeight = 0;int yPos = 0;int listItemNum;List<View> childViews = null;width = ViewUtil.getScreenWidth(context);// 宽度等于屏幕宽ListAdapter listAdapter = listView.getAdapter();listItemNum = listAdapter.getCount();childViews = new ArrayList<View>(listItemNum);View itemView;// 计算整体高度:for (int pos = 0; pos < listItemNum; ++pos) {itemView = listAdapter.getView(pos, null, listView);// measure过程itemView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));childViews.add(itemView);rootHeight += itemView.getMeasuredHeight();}Bitmap bitmap = Bitmap.createBitmap(width, rootHeight, Config.ARGB_8888);Canvas canvas = new Canvas(bitmap);Bitmap itemBitmap;int childHeight;// 把每个ItemView生成图片,并画到背景画布上for (int pos = 0; pos < childViews.size(); ++pos) {itemView = childViews.get(pos);childHeight = itemView.getMeasuredHeight();itemBitmap = viewToBitmap(itemView, width, childHeight);if (itemBitmap != null) {canvas.drawBitmap(itemBitmap, 0, yPos, null);}yPos = childHeight + yPos;}canvas.save(Canvas.ALL_SAVE_FLAG);canvas.restore();return bitmap;}
<span style="white-space:pre"></span>private static Bitmap viewToBitmap(View view, int viewWidth, int viewHeight) {view.layout(0, 0, viewWidth, viewHeight);view.buildDrawingCache();Bitmap bitmap = view.getDrawingCache();return bitmap;}
</pre><pre>
- 截屏相关问题
- 截屏相关
- Android横竖屏相关
- 横竖屏切换相关
- 横竖屏切换相关:
- android 横竖屏 相关
- android锁屏相关
- Android横竖屏相关
- MTK触屏相关
- 横竖屏相关
- 相关
- 相关
- 相关
- 相关
- 相关
- 相关
- 相关
- Android截屏相关以及裁图、保存SD卡
- Xcode7网络请求 需要在info文件中更改的字段
- [python] 小程序
- 内存管理总结
- zookeeper 启动报错 JAVA_HOME is not set
- 深度学习与计算机视觉系列(5)_反向传播与它的直观理解
- 截屏相关
- MongoDB基本命令用
- android 获取状态栏高度
- 如何提高oracle的查询速度(详解)
- 给字符串分配容量
- 《thinking-in-java》读书笔记-第15章-泛型(一)
- jsp九大内置对象
- I/O流类库(四)
- Linux进程监测命令ps