欢迎大家关注我的公众号:**牛角尖尖上起舞**

一般情况下各种型号的手机都会有自带的截屏功能,也会有诸如“开关机键+音量键”的截屏快捷键,只要手机是亮屏状态,都会将手机屏幕的可视区域(包含状态栏)全部截取下来。

如果开发中想要调取系统的截屏功能,理论上讲是可以的,需要在APK中调用“adb shell screencap -pfilepath” 命令,但是需要获取root权限,调用系统的隐藏API。这就很麻烦了,感兴趣的可以自己研究一下,由于实践性很差,这里就不再赘述了。

下面说几种常用截屏和截长图的方法:

一、截屏:

即截取屏幕可视区域内的内容。

1、截取屏幕的整个可视区域(不包含状态栏)

    /*** 截取除了导航栏之外的整个屏幕*/private Bitmap screenShotWholeScreen() {View dView = getWindow().getDecorView();dView.setDrawingCacheEnabled(true);dView.buildDrawingCache();Bitmap bitmap = Bitmap.createBitmap(dView.getDrawingCache());return bitmap;}

效果图:

2、截取某个View在屏幕可视区域内的部分,在可视区域外的部分无法截取到。

原理:利用View的缓存功能。Android为了提供滑动等情况下的性能,可以为每一个View创建缓存,这个缓存实际上就是一个Bitmap对象。

注意:要截取的区域一定要有背景色的设置,比如设置为白色(#ffffff),否则会出现截取后查看图片黑屏,或者分享到微信(QQ、纷享销客等)后黑屏的问题。

    /*** 使用View的缓存功能,截取指定区域的View*/private Bitmap screenShotView(View view) {//开启缓存功能view.setDrawingCacheEnabled(true);//创建缓存view.buildDrawingCache();//获取缓存BitmapBitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());return bitmap;}

效果图:

二、截长图。

比如:当LinearLayout、ScrollView、ListView、WebView的高度超出屏幕高度时,想要截取整个LinearLayout、ScrollView、ListView、WebView的内容。

1、LinearLayout

原理比较简单,将LinearLayout中的子控件的高度一个个获取到,然后在Canvas上利用LinearLayout的draw()方法绘制出来即可。

注意:LinearLayout容器中不能有诸如ListView、WebView这样的高度可变的控件,否则请参照下面专门针对ListView、WebView的方法。

    /*** 截取LinearLayout**/public static Bitmap getLinearLayoutBitmap(LinearLayout linearLayout) {int h = 0;Bitmap bitmap;for (int i = 0; i < linearLayout.getChildCount(); i++) {h += linearLayout.getChildAt(i).getHeight();}// 创建对应大小的bitmapbitmap = Bitmap.createBitmap(linearLayout.getWidth(), h,Bitmap.Config.ARGB_8888);final Canvas canvas = new Canvas(bitmap);linearLayout.draw(canvas);return bitmap;}

2、ScrollView

各位比对代码会发现,原理及实现方式与上述的LinearLayout一模一样。

    /*** 截取scrollview的屏幕**/public static Bitmap getScrollViewBitmap(ScrollView scrollView) {int h = 0;Bitmap bitmap;for (int i = 0; i < scrollView.getChildCount(); i++) {h += scrollView.getChildAt(i).getHeight();}// 创建对应大小的bitmapbitmap = Bitmap.createBitmap(scrollView.getWidth(), h,Bitmap.Config.ARGB_8888);final Canvas canvas = new Canvas(bitmap);scrollView.draw(canvas);return bitmap;}

3、ListView

网上很多帖子中提到的都是下面这个方法,原理和实现代码与上述的LinearLayout和ScrollView一样,然而,实践中发现对于ListView来说,这个方法不好用(好用的方法在后面)。

    /*** 截图listview**/public static Bitmap getListViewBitmap(ListView listView) {int h = 0;Bitmap bitmap;// 获取listView实际高度for (int i = 0; i < listView.getChildCount(); i++) {h += listView.getChildAt(i).getHeight();}Log.d(TAG, "实际高度:" + h);Log.d(TAG, "list 高度:" + listView.getHeight());// 创建对应大小的bitmapbitmap = Bitmap.createBitmap(listView.getWidth(), h,Bitmap.Config.ARGB_8888);final Canvas canvas = new Canvas(bitmap);listView.draw(canvas);return bitmap;}

如果ListView的高度没有超出屏幕可视区域,这个方法可行;

如果ListView的高度没有超出屏幕可视区域,截出来的长图只能看到可视区域内的listitem,不可见区域的listitem由于不可见高度也是0。所以截的图还是只有可视区域的部分。如下图,条目15就被截断了:

原因在于,ListView会回收和重用其item,并且只会绘制可视区域内的item,如果发生滑动,一旦之前可见的item变为不可见,就会被ListView回收,以备重用。这就是不可见区域的item呈现为白屏的原因。(当然,如果你的ListView的背景色是红色,那就是红屏)

那好用的ListView截取长图的方法呢?

代码如下,来源于stackoverflow,原理就是将listitem一个个绘制为小bitmap,然后再将所有小bitmap按顺序组合成大bitmap,即长图。

    /*** http://stackoverflow.com/questions/12742343/android-get-screenshot-of-all-listview-items*/public static Bitmap shotListView(ListView listview) {ListAdapter adapter = listview.getAdapter();int itemscount = adapter.getCount();int allitemsheight = 0;List<Bitmap> bmps = new ArrayList<Bitmap>();for (int i = 0; i < itemscount; i++) {View childView = adapter.getView(i, null, listview);childView.measure(View.MeasureSpec.makeMeasureSpec(listview.getWidth(), View.MeasureSpec.EXACTLY),View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));childView.layout(0, 0, childView.getMeasuredWidth(), childView.getMeasuredHeight());childView.setDrawingCacheEnabled(true);childView.buildDrawingCache();bmps.add(childView.getDrawingCache());allitemsheight += childView.getMeasuredHeight();}int w = listview.getMeasuredWidth();Bitmap bigbitmap = Bitmap.createBitmap(w, allitemsheight, Bitmap.Config.ARGB_8888);Canvas bigcanvas = new Canvas(bigbitmap);Paint paint = new Paint();int iHeight = 0;for (int i = 0; i < bmps.size(); i++) {Bitmap bmp = bmps.get(i);bigcanvas.drawBitmap(bmp, 0, iHeight, paint);iHeight += bmp.getHeight();bmp.recycle();bmp = null;}return bigbitmap;}

看下面的效果图,item没有出现被截断的情况:

4、WebView

这里提供两种方法(两种方法都不完美,怎样变完美请往后面看)。

方法一:

    /*** 截取WebView的屏幕,* * webView.capturePicture()方法在android 4.4(19)版本被废弃,* * 官方建议通过onDraw(Canvas)截屏** @param webView* @return*/private static Bitmap captureWebView(WebView webView) {Picture snapShot = webView.capturePicture();Bitmap bitmap = Bitmap.createBitmap(snapShot.getWidth(),snapShot.getHeight(), Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(bitmap);snapShot.draw(canvas);return bitmap;}

方法二:

    /*** 截取WebView的屏幕,** webView.getScale()方法在android 4.4.2(17)版本被废弃,** 官方建议通过 onScaleChanged(WebView, float, float)回调方法获取缩放率** @param webView* @return*/private static Bitmap getWebViewBitmap(WebView webView) {//获取webview缩放率float scale = webView.getScale();//得到缩放后webview内容的高度int webViewHeight = (int) (webView.getContentHeight() * scale);Bitmap bitmap = Bitmap.createBitmap(webView.getWidth(), webViewHeight, Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(bitmap);//绘制webView.draw(canvas);return bitmap;}

然而,两种方法都不能兼容Android 5.0及5.0以上系统:

A、在android 5.0以下版本的系统中,截WebView长图都可用;

B、在android 5.0及5.0以上版本的系统中,截出来的长图都是不完整的,只有屏幕可视区域内的内容,可视区域外的是白屏。效像下面图示这样:

原因在于,在5.0及以上版本,Android为了降低WebView的内存消耗,对WebView进行了优化:可视区域内的HTML页面进行渲染,不可视区域的HTML显示为白屏,待需要显示时再进行渲染。

解决办法是在设置布局文件的setContentView()方法前调用WebView.enableSlowWholeDocumentDraw(),其作用是禁止Android对WebView进行优化。

//系统版本不小于5.0
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){WebView.enableSlowWholeDocumentDraw();
}

如果项目的minSdkVersion<21,上述方法会报异常 @TargetApi(apiVersion) : Call requires API level 21 (current min is 16)

很好解决,请看我的另一篇博客:Android @TargetApi(apiVersion) : Call requires API level 21 (current min is 16)

至此,WebView的截长图功能也实现了。至于其他未测试到的容器,方法大体相同,请各位自行测试吧!

附一张WebView截长图成功的示例图:

至于网页中图片加载失败,是测试服务器的图片资源发生了移动,与Android代码无关。

欢迎大家关注我的公众号:**牛角尖尖上起舞**

Android 实现截屏和截长图功能的几种方法相关推荐

  1. Android实现截屏和截长图功能的几种方法

    一般情况下各种型号的手机都会有自带的截屏功能,也会有诸如"开关机键+音量键"的截屏快捷键,只要手机是亮屏状态,都会将手机屏幕的可视区域(包含状态栏)全部截取下来. 如果开发中想要调 ...

  2. Android截屏与WebView长图分享经验总结【转】

    原文:https://youzanmobile.github.io/2017/05/19/android-screenshot-and-webview/ 最近在做新业务需求的同时,我们在 Androi ...

  3. Android 截屏与 WebView 长图分享经验总结

    最近在做新业务需求的同时,我们在 Android 上遇到了一些之前没有碰到过的问题,截屏分享. WebView 生成长图以及长图在各个分享渠道分享时图片模糊甚至分享失败等问题,在这过程中踩了很多坑,到 ...

  4. android 截长图 方法,Android实现截屏与截长图功能

    本文实例为大家分享了Android实现截屏与截长图功能展示的具体代码,供大家参考,具体内容如下 Demo在GitHub的地址:ScreenShoot 在Android开发中,有时候会遇到需要截屏分享到 ...

  5. android中最新webview的功能,Android WebView实现截长图功能

    本文实例为大家分享了Android实现截长图功能的具体代码,供大家参考,具体内容如下 先看看手机自带的长截屏功能:  机型: vivo x9 plus 大胆推测实现逻辑: 1:需要一个可以滚动的Vie ...

  6. android webview 图片居中,Android WebView实现截长图功能

    本文实例为大家分享了Android实现截长图功能的具体代码,供大家参考,具体内容如下 先看看手机自带的长截屏功能:  机型: vivo x9 plus 大胆推测实现逻辑: 1:需要一个可以滚动的Vie ...

  7. 追求截图的极致-牛牛截图再添新成员-截长图功能

    很久没有写关于截图控件的文章了,借着这次截图控件新功能升级,向大家介绍一下牛牛截图! 大家知道,我们对于截图控件的功能性.易用性以及体验都有着非常高的要求,总结如下: 能力方面 我们支持多显示器.高清 ...

  8. Tools_@截屏工具@OCR识别工具@图片文字翻译工具长截屏,普通截屏套件推荐(by QQ)@鼠标键盘动作录制

    文章目录 Tools_@截屏工具@OCR识别工具@图片文字翻译工具长截屏,普通截屏套件推荐(QQ自带) 全局录屏/长截屏: OCR 优点 不足 quicker动作 鼠键录制工具

  9. Android实现录屏和截屏功能

    Android实现录屏和截屏功能 1. MediaProjectionManager介绍 2.所需权限 3.示例代码 1. MediaProjectionManager介绍 用于获取screen ca ...

最新文章

  1. 大数据5年规模将达8000亿
  2. python 编程入门-Python编程入门电子书教程,看这几个就够了
  3. php中strtotime的意思,php中strtotime函数用法详解
  4. 梁迪:源于热爱乐于分享,MVP代表圆桌会议
  5. 做了中台就不会死吗?每年至少40%开发资源是被浪费的!
  6. mysql 5.6 5.7不兼容_同一条sql在mysql5.6和5.7版本遇到的问题。
  7. php网站整合ck播放器,wordpress主题整合ckplayer播放器
  8. 论文阅读:Deep forest/深度森林/gcForest
  9. 找到弹窗广告所在的程序文件位置
  10. 查询2021高考成绩位次,2021年江苏高考位次表及高考个人成绩排名查询
  11. 对搜索引擎市场份额调查数据差异之补充
  12. Rdt2.1 和 Rdt2.2的详细解释
  13. 如何在命令行中显示五彩斑斓的“黑”
  14. 那么如何高效管理Linkedin账号
  15. 阿ken的HTML、CSS的学习笔记_CSS3选择器(笔记四)
  16. 数据库操作(增删改查)sql语句
  17. 使用ffmpeg从视频中提取音频文件
  18. Android 语言国际化
  19. flutter在IOS上显示英文
  20. Currency Trading: Dollar in a Funk as Traders Bet on Slow Rebound

热门文章

  1. 搜索引擎中的网络蜘蛛技术探析
  2. Matlab简易版美图秀秀(GUI界面实现)
  3. VS2017社区版Community 许可证过期解决方法
  4. Android学习之 两个Fragment之间传递信息
  5. MySQL中datetime类型23:59:59变成下一天的00:00:00
  6. ZOJ - 1203 Swordfish(最短路)
  7. 阿里云服务器(ECS)优惠券领取
  8. 如何通过自助数据分析实现精准营销?
  9. 《机器人学 》读书笔记
  10. ubuntu五笔死机