打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Android滚动截屏,ScrollView截屏,Listview截屏,Recyclerview截屏

Android滚动截屏,ScrollView截屏,Listview截屏,Recyclerview截屏

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

一: 普通截屏的实现

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

 

  /**   * shot the current screen ,with the status but the status is trans *   *   * @param ctx current activity   */  public static Bitmap shotActivity(Activity ctx) {    View view = ctx.getWindow().getDecorView();    view.setDrawingCacheEnabled(true);    view.buildDrawingCache();    Bitmap bp = Bitmap.createBitmap(view.getDrawingCache(), 0, 0, view.getMeasuredWidth(),        view.getMeasuredHeight());    view.setDrawingCacheEnabled(false);    view.destroyDrawingCache();    return bp;  }

 

 

获取当前View的DrawingCache

 

   public static Bitmap getViewBp(View v) {        if (null == v) {            return null;        }        v.setDrawingCacheEnabled(true);        v.buildDrawingCache();        if (Build.VERSION.SDK_INT >= 11) {            v.measure(MeasureSpec.makeMeasureSpec(v.getWidth(),                    MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(                    v.getHeight(), MeasureSpec.EXACTLY));            v.layout((int) v.getX(), (int) v.getY(),                    (int) v.getX() + v.getMeasuredWidth(),                    (int) v.getY() + v.getMeasuredHeight());        } else {            v.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));            v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());        }        Bitmap b = Bitmap.createBitmap(v.getDrawingCache(), 0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());        v.setDrawingCacheEnabled(false);        v.destroyDrawingCache();        return b;    }

 


二:开源方案

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

 


三: ScrollView截屏

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

 

  /**   * http://blog.csdn.net/lyy1104/article/details/40048329   */  public static Bitmap shotScrollView(ScrollView scrollView) {    int h = 0;    Bitmap bitmap = null;    for (int i = 0; i < scrollView.getChildCount(); i++) {      h += scrollView.getChildAt(i).getHeight();      scrollView.getChildAt(i).setBackgroundColor(Color.parseColor("#ffffff"));    }    bitmap = Bitmap.createBitmap(scrollView.getWidth(), h, Bitmap.Config.RGB_565);    final Canvas canvas = new Canvas(bitmap);    scrollView.draw(canvas);    return bitmap;  }

 

 

 

四: ListView截屏

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

 

/**   * 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();    }    Bitmap bigbitmap =        Bitmap.createBitmap(listview.getMeasuredWidth(), 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;  }

 

 

五: RecyclerView截屏

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

 

/**   * https://gist.github.com/PrashamTrivedi/809d2541776c8c141d9a   */  public static Bitmap shotRecyclerView(RecyclerView view) {    RecyclerView.Adapter adapter = view.getAdapter();    Bitmap bigBitmap = null;    if (adapter != null) {      int size = adapter.getItemCount();      int height = 0;      Paint paint = new Paint();      int iHeight = 0;      final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);      // Use 1/8th of the available memory for this memory cache.      final int cacheSize = maxMemory / 8;      LruCache<String, Bitmap> bitmaCache = new LruCache<>(cacheSize);      for (int i = 0; i < size; i++) {        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) {          bitmaCache.put(String.valueOf(i), drawingCache);        }        height += holder.itemView.getMeasuredHeight();      }      bigBitmap = Bitmap.createBitmap(view.getMeasuredWidth(), height, Bitmap.Config.ARGB_8888);      Canvas bigCanvas = new Canvas(bigBitmap);      Drawable lBackground = view.getBackground();      if (lBackground instanceof ColorDrawable) {        ColorDrawable lColorDrawable = (ColorDrawable) lBackground;        int lColor = lColorDrawable.getColor();        bigCanvas.drawColor(lColor);      }      for (int i = 0; i < size; i++) {        Bitmap bitmap = bitmaCache.get(String.valueOf(i));        bigCanvas.drawBitmap(bitmap, 0f, iHeight, paint);        iHeight += bitmap.getHeight();        bitmap.recycle();      }    }    return bigBitmap;  }

 

 

 

六: 其他屏幕相关工具

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

 

 /**     * get the height of status *     */    public static int getStatusH(Activity ctx) {        Rect s = new Rect();        ctx.getWindow().getDecorView().getWindowVisibleDisplayFrame(s);        return s.top;    }

 

 

 /**     * get the height of status *     */    public static int getStatusH(Context ctx) {        int statusHeight = -1;        try {            Class<?> clazz = Class.forName("com.android.internal.R$dimen");            Object object = clazz.newInstance();            int height = Integer.parseInt(clazz.getField("status_bar_height")                    .get(object).toString());            statusHeight = ctx.getResources().getDimensionPixelSize(height);        } catch (Exception e) {            e.printStackTrace();        }        return statusHeight;    }

 

 

    /**     * get the height of status *     */    public static int getStatusHeight(Activity activity) {        int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");        return resourceId > 0  activity.getResources().getDimensionPixelSize(resourceId) : 0;    }

 

2.获取标题栏高度

 

 /**     * get the height of title *     */    public static int getTitleH(Activity ctx) {        int contentTop = ctx.getWindow()                .findViewById(Window.ID_ANDROID_CONTENT).getTop();        return contentTop - getStatusH(ctx);    }

 

3.获取屏幕宽高

 

 /**     * get the width of screen **     */    public static int getScreenW(Context ctx) {        int w = 0;        if (Build.VERSION.SDK_INT > 13) {            Point p = new Point();            ((WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE))                    .getDefaultDisplay().getSize(p);            w = p.x;        } else {            w = ((WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE))                    .getDefaultDisplay().getWidth();        }        return w;    }

 

 
 /**     * get the height of screen *     */    public static int getScreenH(Context ctx) {        int h = 0;        if (Build.VERSION.SDK_INT > 13) {            Point p = new Point();            ((WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE))                    .getDefaultDisplay().getSize(p);            h = p.y;        } else {            h = ((WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE))                    .getDefaultDisplay().getHeight();        }        return h;    }

 

 /**     * 获得屏幕高度     *     * @param context     * @return     */    public static int getScreenWidth(Context context) {        WindowManager wm = (WindowManager) context                .getSystemService(Context.WINDOW_SERVICE);        DisplayMetrics outMetrics = new DisplayMetrics();        wm.getDefaultDisplay().getMetrics(outMetrics);        return outMetrics.widthPixels;    }

 


相关源码:

ScreenUtil@[Github]

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
[android]ScrollView设置滚动条的位置
Android开发之漫漫长途 XVI——ListView与RecyclerView项目实战
ScrollView 嵌套listview或者gridview 不再顶部的解决办法
开发中的问题
Android实现截屏方式整理(总结)
让你彻底掌握RecyclerView的缓存机制
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服