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],原理圖如下:

 

illustration


三: 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]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM