Android应用开发Android 普通View截图 RecyclerView截图 ScrollView截图分享
白羽 2019-03-25 来源 :网络 阅读 880 评论 0

摘要:本文将带你了解Android应用开发Android 普通View截图 RecyclerView截图 ScrollView截图分享,希望本文对大家学Android有所帮助。

    本文将带你了解Android应用开发Android 普通View截图 RecyclerView截图 ScrollView截图分享,希望本文对大家学Android有所帮助。



Android应用开发Android 普通View截图 RecyclerView截图 ScrollView截图分享



    思路
      实际开发中经常会遇到应用内截图的相关问题,如果是普通View的话我们可以使用View的绘图缓存来获取截图,但是RecyclerView和ScrollView呢就稍微有点不同了。ScrollView还好,只有一个子View,而RecyclerView中会有itemView重用的问题,只会绘制在屏幕上显示出来的itemView,因此我们可以依次获取每个itemView的视图存储到LruCache中,最后在进行拼装。这种方案有个问题就是如果数据过多可能会产生OOM问题,不过我测试的几百条item都还好,没有遇到。
   
    代码
    普通View
    普通View截图就是获取View的绘图缓存,这里的代码很简单,先看看吧:
   
  
    //开启绘图缓存
              view.setDrawingCacheEnabled(true);
              //这个方法可调可不调,因为在getDrawingCache()里会自动判断有没有缓存有没有准备好,
              //如果没有,会自动调用buildDrawingCache()
              view.buildDrawingCache();
            //获取绘图缓存   这里直接创建了一个新的bitmap
            //因为我们在最后需要释放缓存资源,会释放掉缓存中创建的bitmap对象
            Bitmap bitmap =   Bitmap.createBitmap(view.getDrawingCache(), 0, 0,   view.getMeasuredWidth(),
                    view.getMeasuredHeight());
            //清理绘图缓存,释放资源
              view.destroyDrawingCache();

    可以看下destroyDrawingCache()方法的源码:
   
  
    public void   destroyDrawingCache() {
            if (mDrawingCache != null)   {
                  mDrawingCache.recycle();
                mDrawingCache =   null;
            }
            if (mUnscaledDrawingCache !=   null) {
                  mUnscaledDrawingCache.recycle();
                mUnscaledDrawingCache = null;
            }
          }

      如果你需要整个屏幕的截图,使用了DecorView来获取截图的话顶部会有状态栏的一条,可以通过获取状态栏高度,在重新创建Bitmap时截取掉。
   
    RecyclerView截图
      RecyclerView的截图稍微复杂些。我们可以先获取到rv的adapter对象,通过adapter对象手动调用创建和绑定ViewHolder等方法,模拟rv的加载过程,再依次保存每个itemView的绘图缓存,最后拼装成一个完整的Bitmap。看看代码吧~
    1. 获取Adapter,通过Adapter获取每个itemView的绘图缓存
    “` java
    //获取设置的adapter
    RecyclerView.Adapter adapter = view.getAdapter();
    if (adapter == null) {
    return null;
    }
    //创建保存截图的bitmap
    Bitmap bigBitmap = null;
    //获取item的数量
    int size = adapter.getItemCount();
    //recycler的完整高度 用于创建bitmap时使用
    int height = 0;
    //获取最大可用内存
    final int maxMemory = (int) (Runtime.getRuntime().maxMemory() /   1024);
   

          // 使用1/8的缓存
        final int cacheSize = maxMemory /   8;
        //把每个item的绘图缓存存储在LruCache中
        LruCache  bitmapCache = new LruCache<>(cacheSize);
        for (int i = 0; i < size; i++)   {
              //手动调用创建和绑定ViewHolder方法,
            RecyclerView.ViewHolder   holder = adapter.createViewHolder(view, adapter.getItemViewType(i));
              adapter.onBindViewHolder(holder, i);
            //测量
              holder.itemView.measure(
                      View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY),
                      View.MeasureSpec.makeMeasureSpec(0,   View.MeasureSpec.UNSPECIFIED));
            //布局
            holder.itemView.layout(0, 0,   holder.itemView.getMeasuredWidth(),
                      holder.itemView.getMeasuredHeight());
            //开启绘图缓存
              holder.itemView.setDrawingCacheEnabled(true);
              holder.itemView.buildDrawingCache();
            Bitmap drawingCache =   holder.itemView.getDrawingCache();
            if (drawingCache != null)   {
                  bitmapCache.put(String.valueOf(i), drawingCache);
            }
            //获取itemView的实际高度并累加
            height +=   holder.itemView.getMeasuredHeight();
        }
     

   
    2. 创建保存截图的Bitmap 把保存的itemView绘图缓存画上去
    java
    //根据计算出的recyclerView高度创建bitmap
    bigBitmap = Bitmap.createBitmap(view.getMeasuredWidth(), height,   Bitmap.Config.RGB_565);
    //创建一个canvas画板
    Canvas canvas = new Canvas(bigBitmap);
    //获取recyclerView的背景颜色
    Drawable background = view.getBackground();
    //画出recyclerView的背景色 这里只用了color一种 有需要也可以自己扩展
    if (background instanceof ColorDrawable) {
    ColorDrawable colorDrawable = (ColorDrawable) background;
    int color = colorDrawable.getColor();
    canvas.drawColor(color);
    }
    //当前bitmap的高度
    int top = 0;
    //画笔
    Paint paint = new Paint();
    for (int i = 0; i < size; i++) {
    Bitmap bitmap = bitmapCache.get(String.valueOf(i));
    canvas.drawBitmap(bitmap, 0f, top, paint);
    top += bitmap.getHeight();
    }
    “`
   
    ScrollView截图
    ScrollView的截图也比较简单,获取到子View的高度就好,而ScrollView只允许又一个子View。
 

        int height = 0;
            //理论上scrollView只会有一个子View啦
            for (int i = 0; i <   view.getChildCount(); i++) {
                height +=   view.getChildAt(i).getHeight();
            }
            //创建保存缓存的bitmap
            Bitmap bitmap =   Bitmap.createBitmap(view.getWidth(), height, Bitmap.Config.RGB_565);
            //可以简单的把Canvas理解为一个画板   而bitmap就是块画布
            Canvas canvas = new   Canvas(bitmap);
            //获取ScrollView的背景颜色
            Drawable background =   view.getBackground();
            //画出ScrollView的背景色   这里只用了color一种 有需要也可以自己扩展 也可以自己直接指定一种背景色
            if (background instanceof   ColorDrawable) {
                ColorDrawable   colorDrawable = (ColorDrawable) background;
                int color =   colorDrawable.getColor();
                  canvas.drawColor(color);
            }
              //把view的内容都画到指定的画板Canvas上
            view.draw(canvas);
            return   bitmap;

    关于Bitmap的recycle()方法
    很多人以为这个释放资源的方法是必须调用的。其实不然,在2.3之后可以完全交由GC管理。具体的解释可以参见官方注释
   
    Free the native object associated with this bitmap, and clear the
    reference to the pixel data. This will not free the pixel data   synchronously;
    it simply allows it to be garbage collected if there are no other   references.
    The bitmap is marked as “dead”, meaning it will throw an exception if
    getPixels() or setPixels() is called, and will draw nothing. This   operation
    cannot be reversed, so it should only be called if you are sure there are   no
    further uses for the bitmap. This is an advanced call, and normally   need
    not be called, since the normal GC process will free up this memory   when
    there are no more references to this bitmap.
   

        

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之Android频道!

本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程