在做分享功能的時候,需要截取全屏內(nèi)容,一屏展示不完的內(nèi)容,一般我們會用到 ListView 或 ScrollView
1:普通截屏的實現(xiàn)
獲取當(dāng)前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;
}
[注意:在viewpager里由于來回滑動導(dǎo)致你在position 0的位置卻截了position 1的圖片,這時加上view.getRootView().invalidate()或者getActivity().getWindow().getDecorView().invalidate()]
獲取當(dāng)前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;
}
二:開源
在滾動視圖中,如果當(dāng)前View并沒有在視圖中全部繪制出來,我們可以利用View的ScrollTo()和ScrollBy()方法來移動畫布,同時獲取當(dāng)前View的可視部分的DrawingCache,最后進行拼接得到其Bitmap,參考:,
三: ScrollView截屏
三個截屏中,ScrollView最簡單,因為ScrollView只有一個childView,雖然沒有全部顯示在界面上,但是已經(jīng)全部渲染繪制,因此可以直接 調(diào)用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,根據(jù)stackoverflow上大神的建議,采用一個List來存儲Item的視圖,這種方案依然不夠好,當(dāng)Item足夠多的時候,可能會發(fā)生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版本中,已經(jīng)可以用RecyclerView來代替使用ListView的場景,相比較ListView,RecyclerView對Item View的緩存支持的更好??梢圆捎煤蚅istView相同的方案,這里也是在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;
}
六: 其他屏幕相關(guān)工具
1.獲取狀態(tài)來高度常見方式
/**
* 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.獲取標(biāo)題欄高度
/**
* 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;
}