在做分享功能的时候,需要截取全屏内容,一屏展示不完的内容,一般我们会用到 ListView ,ScrollView或Recyclerview

一: 普通截屏的实现

获取当前Window 的 DrawingCache 的方式,即decorView的DrawingCache

  1. /**
  2. * shot the current screen ,with the status but the status is trans *
  3. *
  4. * @param ctx current activity
  5. */
  6. public static Bitmap shotActivity(Activity ctx) {
  7.  
  8. View view = ctx.getWindow().getDecorView();
  9. view.setDrawingCacheEnabled(true);
  10. view.buildDrawingCache();
  11.  
  12. Bitmap bp = Bitmap.createBitmap(view.getDrawingCache(), , , view.getMeasuredWidth(),
  13. view.getMeasuredHeight());
  14.  
  15. view.setDrawingCacheEnabled(false);
  16. view.destroyDrawingCache();
  17.  
  18. return bp;
  19. }

获取当前View的DrawingCache

  1. public static Bitmap getViewBp(View v) {
  2. if (null == v) {
  3. return null;
  4. }
  5. v.setDrawingCacheEnabled(true);
  6. v.buildDrawingCache();
  7. if (Build.VERSION.SDK_INT >= ) {
  8. v.measure(MeasureSpec.makeMeasureSpec(v.getWidth(),
  9. MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
  10. v.getHeight(), MeasureSpec.EXACTLY));
  11. v.layout((int) v.getX(), (int) v.getY(),
  12. (int) v.getX() + v.getMeasuredWidth(),
  13. (int) v.getY() + v.getMeasuredHeight());
  14. } else {
  15. v.measure(MeasureSpec.makeMeasureSpec(, MeasureSpec.UNSPECIFIED),
  16. MeasureSpec.makeMeasureSpec(, MeasureSpec.UNSPECIFIED));
  17. v.layout(, , v.getMeasuredWidth(), v.getMeasuredHeight());
  18. }
  19. Bitmap b = Bitmap.createBitmap(v.getDrawingCache(), , , v.getMeasuredWidth(), v.getMeasuredHeight());
  20.  
  21. v.setDrawingCacheEnabled(false);
  22. v.destroyDrawingCache();
  23. return b;
  24. }


二:开源方案

在滚动视图中,如果当前View并没有在视图中全部绘制出来,我们可以利用View的ScrollTo()和ScrollBy()方法来移动画布,同时获取当前View的可视部分的DrawingCache,最后进行拼接得到其Bitmap,参考:PGSSoft/scrollscreenshot@[Github],原理图如下:


三: ScrollView截屏

三个截屏中,ScrollView最简单,因为ScrollView只有一个childView,虽然没有全部显示在界面上,但是已经全部渲染绘制,因此可以直接 调用`scrollView.draw(canvas)`来完成截图,

  1. /**
  2. * http://blog.csdn.net/lyy1104/article/details/40048329
  3. */
  4. public static Bitmap shotScrollView(ScrollView scrollView) {
  5. int h = ;
  6. Bitmap bitmap = null;
  7. for (int i = ; i < scrollView.getChildCount(); i++) {
  8. h += scrollView.getChildAt(i).getHeight();
  9. scrollView.getChildAt(i).setBackgroundColor(Color.parseColor("#ffffff"));
  10. }
  11. bitmap = Bitmap.createBitmap(scrollView.getWidth(), h, Bitmap.Config.RGB_565);
  12. final Canvas canvas = new Canvas(bitmap);
  13. scrollView.draw(canvas);
  14. return bitmap;
  15. }

四: ListView截屏

而ListView就是会回收与重用Item,并且只会绘制在屏幕上显示的ItemView,根据stackoverflow上大神的建议,采用一个List来存储Item的视图,这种方案依然不够好,当Item足够多的时候,可能会发生oom。

  1. /**
  2. * http://stackoverflow.com/questions/12742343/android-get-screenshot-of-all-listview-items
  3. */
  4. public static Bitmap shotListView(ListView listview) {
  5.  
  6. ListAdapter adapter = listview.getAdapter();
  7. int itemscount = adapter.getCount();
  8. int allitemsheight = ;
  9. List<Bitmap> bmps = new ArrayList<Bitmap>();
  10.  
  11. for (int i = ; i < itemscount; i++) {
  12.  
  13. View childView = adapter.getView(i, null, listview);
  14. childView.measure(
  15. View.MeasureSpec.makeMeasureSpec(listview.getWidth(), View.MeasureSpec.EXACTLY),
  16. View.MeasureSpec.makeMeasureSpec(, View.MeasureSpec.UNSPECIFIED));
  17.  
  18. childView.layout(, , childView.getMeasuredWidth(), childView.getMeasuredHeight());
  19. childView.setDrawingCacheEnabled(true);
  20. childView.buildDrawingCache();
  21. bmps.add(childView.getDrawingCache());
  22. allitemsheight += childView.getMeasuredHeight();
  23. }
  24.  
  25. Bitmap bigbitmap =
  26. Bitmap.createBitmap(listview.getMeasuredWidth(), allitemsheight, Bitmap.Config.ARGB_8888);
  27. Canvas bigcanvas = new Canvas(bigbitmap);
  28.  
  29. Paint paint = new Paint();
  30. int iHeight = ;
  31.  
  32. for (int i = ; i < bmps.size(); i++) {
  33. Bitmap bmp = bmps.get(i);
  34. bigcanvas.drawBitmap(bmp, , iHeight, paint);
  35. iHeight += bmp.getHeight();
  36.  
  37. bmp.recycle();
  38. bmp = null;
  39. }
  40.  
  41. return bigbitmap;
  42. }

五: RecyclerView截屏

我们都知道,在新的Android版本中,已经可以用RecyclerView来代替使用ListView的场景,相比较ListView,RecyclerView对Item View的缓存支持的更好。可以采用和ListView相同的方案,这里也是在stackoverflow上看到的方案。

  1. /**
  2. * https://gist.github.com/PrashamTrivedi/809d2541776c8c141d9a
  3. */
  4. public static Bitmap shotRecyclerView(RecyclerView view) {
  5. RecyclerView.Adapter adapter = view.getAdapter();
  6. Bitmap bigBitmap = null;
  7. if (adapter != null) {
  8. int size = adapter.getItemCount();
  9. int height = ;
  10. Paint paint = new Paint();
  11. int iHeight = ;
  12. final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / );
  13.  
  14. // Use 1/8th of the available memory for this memory cache.
  15. final int cacheSize = maxMemory / ;
  16. LruCache<String, Bitmap> bitmaCache = new LruCache<>(cacheSize);
  17. for (int i = ; i < size; i++) {
  18. RecyclerView.ViewHolder holder = adapter.createViewHolder(view, adapter.getItemViewType(i));
  19. adapter.onBindViewHolder(holder, i);
  20. holder.itemView.measure(
  21. View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY),
  22. View.MeasureSpec.makeMeasureSpec(, View.MeasureSpec.UNSPECIFIED));
  23. holder.itemView.layout(, , holder.itemView.getMeasuredWidth(),
  24. holder.itemView.getMeasuredHeight());
  25. holder.itemView.setDrawingCacheEnabled(true);
  26. holder.itemView.buildDrawingCache();
  27. Bitmap drawingCache = holder.itemView.getDrawingCache();
  28. if (drawingCache != null) {
  29.  
  30. bitmaCache.put(String.valueOf(i), drawingCache);
  31. }
  32. height += holder.itemView.getMeasuredHeight();
  33. }
  34.  
  35. bigBitmap = Bitmap.createBitmap(view.getMeasuredWidth(), height, Bitmap.Config.ARGB_8888);
  36. Canvas bigCanvas = new Canvas(bigBitmap);
  37. Drawable lBackground = view.getBackground();
  38. if (lBackground instanceof ColorDrawable) {
  39. ColorDrawable lColorDrawable = (ColorDrawable) lBackground;
  40. int lColor = lColorDrawable.getColor();
  41. bigCanvas.drawColor(lColor);
  42. }
  43.  
  44. for (int i = ; i < size; i++) {
  45. Bitmap bitmap = bitmaCache.get(String.valueOf(i));
  46. bigCanvas.drawBitmap(bitmap, 0f, iHeight, paint);
  47. iHeight += bitmap.getHeight();
  48. bitmap.recycle();
  49. }
  50. }
  51. return bigBitmap;
  52. }
  1.  

六: 其他屏幕相关工具

1.获取状态来高度常见方式

  1. /**
  2. * get the height of status *
  3. */
  4. public static int getStatusH(Activity ctx) {
  5. Rect s = new Rect();
  6. ctx.getWindow().getDecorView().getWindowVisibleDisplayFrame(s);
  7. return s.top;
  8. }
  1. /**
  2. * get the height of status *
  3. */
  4. public static int getStatusH(Context ctx) {
  5. int statusHeight = -;
  6. try {
  7. Class<?> clazz = Class.forName("com.android.internal.R$dimen");
  8. Object object = clazz.newInstance();
  9. int height = Integer.parseInt(clazz.getField("status_bar_height")
  10. .get(object).toString());
  11. statusHeight = ctx.getResources().getDimensionPixelSize(height);
  12. } catch (Exception e) {
  13. e.printStackTrace();
  14. }
  15. return statusHeight;
  16. }
  1. /**
  2. * get the height of status *
  3. */
  4. public static int getStatusHeight(Activity activity) {
  5. int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
  6. return resourceId > ? activity.getResources().getDimensionPixelSize(resourceId) : ;
  7. }
  1.  

2.获取标题栏高度

  1. /**
  2. * get the height of title *
  3. */
  4. public static int getTitleH(Activity ctx) {
  5. int contentTop = ctx.getWindow()
  6. .findViewById(Window.ID_ANDROID_CONTENT).getTop();
  7. return contentTop - getStatusH(ctx);
  8. }

3.获取屏幕宽高

  1. /**
  2. * get the width of screen **
  3. */
  4. public static int getScreenW(Context ctx) {
  5. int w = ;
  6. if (Build.VERSION.SDK_INT > ) {
  7. Point p = new Point();
  8. ((WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE))
  9. .getDefaultDisplay().getSize(p);
  10. w = p.x;
  11. } else {
  12. w = ((WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE))
  13. .getDefaultDisplay().getWidth();
  14. }
  15. return w;
  16. }
  1.  
  1. /**
  2. * get the height of screen *
  3. */
  4. public static int getScreenH(Context ctx) {
  5. int h = ;
  6. if (Build.VERSION.SDK_INT > ) {
  7. Point p = new Point();
  8. ((WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE))
  9. .getDefaultDisplay().getSize(p);
  10. h = p.y;
  11. } else {
  12. h = ((WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE))
  13. .getDefaultDisplay().getHeight();
  14. }
  15. return h;
  16. }
  1. /**
  2. * 获得屏幕高度
  3. *
  4. * @param context
  5. * @return
  6. */
  7. public static int getScreenWidth(Context context) {
  8. WindowManager wm = (WindowManager) context
  9. .getSystemService(Context.WINDOW_SERVICE);
  10. DisplayMetrics outMetrics = new DisplayMetrics();
  11. wm.getDefaultDisplay().getMetrics(outMetrics);
  12. return outMetrics.widthPixels;
  13. }

相关源码:

ScreenUtil@[Github]

Android滚动截屏,ScrollView截屏的更多相关文章

  1. android 滚动视图(ScrollView)

    为了可以让内嵌布局管理器之中加入多个显示的组件,而且又保证程序不这么冗余,所以可以通过 Activity程序进行控制,向内嵌布局管理器中添加多个组件. ScrollView提供一个显示的容器,可以包含 ...

  2. Android长截屏-- ScrollView,ListView及RecyclerView截屏

    http://blog.csdn.net/wbwjx/article/details/46674157       Android长截屏-- ScrollView,ListView及RecyclerV ...

  3. Android 禁止截屏、录屏 — 解决PopupWindow无法禁止录屏问题

    项目开发中,为了用户信息的安全,会有禁止页面被截屏.录屏的需求. 这类资料,在网上有很多,一般都是通过设置Activity的Flag解决,如: //禁止页面被截屏.录屏 getWindow().add ...

  4. 搭建前端监控系统(六)JS截屏和录屏篇

    怎样定位前端线上问题,一直以来,都是很头疼的问题,因为它发生于用户的一系列操作之后.错误的原因可能源于机型,网络环境,接口请求,复杂的操作行为等等,在我们想要去解决的时候很难复现出来,自然也就无法解决 ...

  5. Chrome截图截满滑动栏,QQ截长屏,录屏

    1.Chrome截图截满滑动栏 一般我们截图都是用QQ的Ctrl+shift+A,但是网页不好截,这里我们可以用Chrome控制台来截全网页: F12或Ctrl+shift+i打开控制台: 点击一下控 ...

  6. Android -- 距离感应器控制屏幕灭屏白屏

    权限                                                                                             <u ...

  7. (转)android中利用 ViewPage 实现滑动屏

    最近实现了这样的一个效果:滑动界面出现拖拽效果,可翻动3屏,也可点击按钮翻动页面. 主要利用android.support.v4.view.ViewPager控件来实现. 第一个界面: 滑动屏幕: 换 ...

  8. jquery 单行滚动、批量多行滚动、文字图片翻屏滚动效果代码

    jquery单行滚动.批量多行滚动.文字图片翻屏滚动效果代码,需要的朋友可以参考下. 以下代码,运行后,需要刷新下,才能加载jquery,要不然看不到效果.一.单行滚动效果 <!DOCTYPE ...

  9. Android 设置ListView不可滚动 及在ScrollView中不可滚动的设置

    http://m.blog.csdn.net/blog/yusewuhen/43706169 转载请注明出处: http://blog.csdn.net/androiddevelop/article/ ...

随机推荐

  1. java高精度数组

    POJ1205 递推公式为a[i] = 3*a[i-1] - a[i-2], a[1] = 1,a[2] = 3 , i 最高为100; 搞懂了使用BigInteger开数组. import java ...

  2. jquery cleditor 光标经常点不进去问题解决方法 bootstrap 富文本框 控件

    cleditor 光标点不进去,原因是内嵌的html代码段 body没有赋值默认高度. 解决方法1.赋值options.bodyStyle  设置min-height值.缺点:不能跟随设备更新最低高度 ...

  3. 解决Maven中Missing artifact javax.jms:jms:jar:1.1:compile

    搭建好项目后报错: Missing artifact javax.jms:jms:jar:1.1:compile  于POM.xml中 解决方案: 一 :在nexus中配置一个代理仓库     地址为 ...

  4. ASP.NET关于引用bootstrap.css导致Gridview Header无法居中

    HorizontalAlign="Center"  属性因不知名原因被覆盖掉. 可以使用<HeaderStyle  CssClass="text-center&qu ...

  5. 应用tomcat(Linux中安装)

    CentOS 7 中安装 tomcat. 下载 Tomcat Wget 下载 Tomcat Tomcat 官网中找到指定版本 Tomcat rpm 的 url 使用 wget url 下载 rpm , ...

  6. cf E. Fox and Card Game

    http://codeforces.com/contest/389/problem/E 题意:给你n个序列,然后两个人x,y,两个人玩游戏,x从序列的前面取,y从序列的后面取,两个人都想自己得到的数的 ...

  7. JavaScript encodeURI() 函数

    encodeURI() 函数可把字符串作为 URI 进行编码. -------------------------------------------------------------------- ...

  8. 普通table表格样式及代码大全(全)

    普通table表格样式及代码大全(全)(一) 单实线边框表格 <TABLE style="BORDER-COLLAPSE: collapse" borderColor=#00 ...

  9. 带你走进EJB--MDB实现发送邮件(1)

    在实际的项目中我们有这样的需求,用户注册网站成功之后系统会自动的给注册用户发送注册成功通知邮件,而发送通知邮件的具体过程我们可以通过MDB来实现. 在用MDB来实现发送通知过程之前我们需要先了解一下J ...

  10. 「Poetize6」Candle

    描述 蜡烛商店中有10种蜡烛,形状分别是0~9这10个数字,不过对于每种蜡烛,商店的存货量仅有一根.另外,忘川沧月已经有了一个"+"形状的蜡烛.忘川沧月想购买一些蜡烛,使得他的家族 ...