在做分享功能的时候,需要截取全屏内容,一屏展示不完的内容,一般我们会用到 ListView 或 ScrollView
一: 普通截屏的实现
获取当前Window 的 DrawingCache 的方式,即decorView的DrawingCache
/** * shot the current screen ,with the status but the status is trans * * * @param ctx current activity */ public static Bitmap shotScreen(Activity ctx) { View view = ctx.getWindow().getDecorView(); view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bp = Bitmap.createBitmap(view.getDrawingCache(), 0, 0, getScreenW(ctx), getScreenH(ctx)); 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; }
二:ScrollView截屏实现
在滚动视图中,我们可以利用View的ScrollTo()和ScrollBy()方法来移动画布,同时获取当前View的可视部分的DrawingCache,最后进行拼接得到其Bitmap,参考:PGSSoft/scrollscreenshot@[Github],原理图如下:
三: Padding处理
通过上面方法需要处理的就是View的paddingBottom,每次获取当前屏幕的DrawingCache的时候都会又一个PaddingBottom,拼接起来会有空白分隔,因此有了如下方法。
1.获取当前View的DrawingCache,不包括PaddingBottom
public static Bitmap getViewBpWithoutBottom(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 bp = Bitmap.createBitmap(v.getDrawingCache(), 0, 0, v.getMeasuredWidth(), v.getMeasuredHeight() - v.getPaddingBottom()); v.setDrawingCacheEnabled(false); v.destroyDrawingCache(); return bp; }
2.滚动当前视图,直到达到当前View的Bottom
/** * get the bitmap of a scrollView * */ public static Bitmap getViewBitmap(Context ctx, ScrollView sv) { if (null == sv) { return null; } // enable something sv.setVerticalScrollBarEnabled(false); sv.setVerticalFadingEdgeEnabled(false); sv.scrollTo(0, 0); sv.setDrawingCacheEnabled(true); sv.buildDrawingCache(true); Bitmap b = getViewBpWithoutBottom(sv); /** * vh : the height of the scrollView that is visible <BR> * th : the total height of the scrollView <BR> **/ int vh = sv.getHeight(); int th = sv.getChildAt(0).getHeight(); /** the total height is more than one screen */ if (th > vh) { int w = getScreenW(ctx); int absVh = vh - sv.getPaddingTop() - sv.getPaddingBottom(); do { int restHeight = th - vh; Bitmap temp = null; if (restHeight <= absVh) { sv.scrollBy(0, restHeight); vh += restHeight; temp = getViewBp(sv); } else { sv.scrollBy(0, absVh); vh += absVh; temp = getViewBpWithoutBottom(sv); } b = mergeBitmap(vh, w, temp, 0, sv.getScrollY(), b, 0, 0); } while (vh < th); } // restore somthing sv.scrollTo(0, 0); sv.setVerticalScrollBarEnabled(true); sv.setVerticalFadingEdgeEnabled(true); sv.setDrawingCacheEnabled(false); sv.destroyDrawingCache(); return b; }
3.bitmap拼接
public static Bitmap mergeBitmap(int newImageH, int newIamgeW, Bitmap background, float backX, float backY, Bitmap foreground, float foreX, float foreY) { if (null == background || null == foreground) { return null; } // create the new blank bitmap 创建一个新的和SRC长度宽度一样的位图 Bitmap newbmp = Bitmap.createBitmap(newIamgeW, newImageH, Config.RGB_565); Canvas cv = new Canvas(newbmp); // draw bg into cv.drawBitmap(background, backX, backY, null); // draw fg into cv.drawBitmap(foreground, foreX, foreY, null); // save all clip cv.save(Canvas.ALL_SAVE_FLAG);// 保存 // store cv.restore();// 存储 return newbmp; }
四: 其他屏幕相关工具
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; }
使用Demo:ScreenShotActivity@[Github]