captureType = new CaptureType<>();
30 | captureType.of(t);
31 | return captureType;
32 | }
33 |
34 | /**
35 | * capture RecyclerView
36 | *
37 | * currently only support {@link LinearLayoutManager#VERTICAL}
38 | */
39 | @NonNull
40 | public static CaptureType with(@NonNull RecyclerView view) {
41 | return getCaptureManager(view);
42 | }
43 |
44 | /**
45 | * capture ListView
46 | */
47 | @NonNull
48 | public static CaptureType with(@NonNull ListView view) {
49 | return getCaptureManager(view);
50 | }
51 |
52 | /**
53 | * capture ScrollView
54 | */
55 | @NonNull
56 | public static CaptureType with(@NonNull ScrollView view) {
57 | return getCaptureManager(view);
58 | }
59 |
60 | /**
61 | * capture HorizontalScrollView
62 | */
63 | @NonNull
64 | public static CaptureType with(@NonNull HorizontalScrollView view) {
65 | return getCaptureManager(view);
66 | }
67 |
68 | /**
69 | * capture WebView
70 | *
71 | * take case of ,set {@link WebView#enableSlowWholeDocumentDraw()} on onCreate() method
72 | */
73 | @NonNull
74 | public static CaptureType with(@NonNull WebView view) {
75 | return getCaptureManager(view);
76 | }
77 |
78 | /**
79 | * capture general view
80 | */
81 | @NonNull
82 | public static CaptureType with(@NonNull View view) {
83 | return getCaptureManager(view);
84 | }
85 |
86 | /**
87 | * capture window by android 5.0+ API
88 | *
89 | * {@link MediaProjectionManager}
90 | * {@link MediaProjection}
91 | * {@link VirtualDisplay}
92 | *
93 | * please choose {@link CaptureType#getBitmap(CaptureCallback)} when you call get bitmap
94 | */
95 | @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
96 | @NonNull
97 | public static CaptureType with(@NonNull Activity activity) {
98 | return getCaptureManager(activity);
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/viewcapture/src/main/java/com/hd/viewcapture/capture/Capture.java:
--------------------------------------------------------------------------------
1 | package com.hd.viewcapture.capture;
2 |
3 | import android.graphics.Bitmap;
4 | import android.support.annotation.NonNull;
5 | import android.support.annotation.Nullable;
6 |
7 | import com.hd.viewcapture.capture.helper.CaptureCallback;
8 |
9 | /**
10 | * Created by hd on 2018/2/6 .
11 | *
12 | */
13 | public abstract class Capture {
14 |
15 | private CaptureCallback callback;
16 |
17 | public abstract Bitmap capture(@NonNull T t);
18 |
19 | public void injectCallback(@NonNull CaptureCallback callback){
20 | this.callback=callback;
21 | }
22 |
23 | protected void report(@Nullable Bitmap bitmap){
24 | if(callback!=null)callback.report(bitmap);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/viewcapture/src/main/java/com/hd/viewcapture/capture/helper/CaptureCallback.java:
--------------------------------------------------------------------------------
1 | package com.hd.viewcapture.capture.helper;
2 |
3 | import android.graphics.Bitmap;
4 | import android.support.annotation.Nullable;
5 |
6 | /**
7 | * Created by hd on 2018/5/30 .
8 | */
9 | public interface CaptureCallback {
10 |
11 | void report(@Nullable Bitmap bitmap);
12 | }
13 |
--------------------------------------------------------------------------------
/viewcapture/src/main/java/com/hd/viewcapture/capture/helper/HorizontalScrollCaptureHelper.java:
--------------------------------------------------------------------------------
1 | package com.hd.viewcapture.capture.helper;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Canvas;
5 | import android.support.annotation.NonNull;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | /**
10 | * Created by hd on 2018/2/8 .
11 | * horizontal Scroll Capture
12 | */
13 | public class HorizontalScrollCaptureHelper implements ScrollCaptureHelper {
14 |
15 | @Override
16 | public Bitmap scrollCapture(T t) {
17 | int currentX = t.getScrollX();
18 | int currentY = t.getScrollY();
19 | try {
20 | enableSomething(t);
21 | return scrollCaptureView(t);
22 | } finally {
23 | restoreSomething(t, currentX, currentY);
24 | }
25 | }
26 |
27 | private Bitmap scrollCaptureView(@NonNull T t) {
28 | Bitmap b = getViewBpWithoutBottom(t);
29 | //the width of the T that is visible
30 | int vW = t.getMeasuredWidth();
31 | //the total width of the T
32 | int tW = ((ViewGroup) t).getChildAt(0).getMeasuredWidth();
33 | Bitmap temp;
34 | //the total width is more than one screen
35 | int a = 0;
36 | if (tW > vW) {
37 | int h = t.getMeasuredHeight();
38 | //max visible width
39 | int absVh = vW - t.getPaddingLeft() - t.getPaddingRight();
40 | do {
41 | a++;
42 | int restWidth = tW - vW;
43 | if (restWidth <= absVh) {
44 | if (a % 2 != 0) {
45 | restWidth = restWidth - t.getPaddingLeft() - t.getPaddingRight();
46 | } else {
47 | restWidth = restWidth + t.getPaddingLeft() + t.getPaddingRight();
48 | }
49 | t.scrollBy(restWidth, 0);
50 | vW += restWidth;
51 | temp = getViewBp(t);
52 | } else {
53 | t.scrollBy(absVh, 0);
54 | if (a / 2 == 0) {
55 | vW += absVh - t.getPaddingRight();
56 | } else {
57 | vW += absVh;
58 | }
59 | temp = getViewBp(t);
60 | }
61 | b = mergeBitmap(t, b, vW, temp, h);
62 | } while (vW < tW);
63 | }
64 | return b;
65 | }
66 |
67 | @NonNull
68 | private Bitmap mergeBitmap(@NonNull T t, Bitmap b, int vW, Bitmap temp, int h) {
69 | Bitmap newbmp = Bitmap.createBitmap(vW, h, Bitmap.Config.RGB_565);
70 | Canvas cv = new Canvas(newbmp);
71 | // draw bg into
72 | cv.drawBitmap(temp, t.getScrollX(), 0, null);
73 | // draw fg into
74 | cv.drawBitmap(b, 0, 0, null);
75 | // save all clip
76 | cv.save(Canvas.ALL_SAVE_FLAG);
77 | // store
78 | cv.restore();
79 | return newbmp;
80 | }
81 |
82 | private void restoreSomething(@NonNull T t, int currentX, int currentY) {
83 | t.scrollTo(currentX, currentY);
84 | t.setHorizontalFadingEdgeEnabled(true);
85 | t.setHorizontalScrollBarEnabled(true);
86 | t.setDrawingCacheEnabled(false);
87 | t.destroyDrawingCache();
88 | }
89 |
90 | private void enableSomething(@NonNull T t) {
91 | t.setHorizontalFadingEdgeEnabled(false);
92 | t.setHorizontalScrollBarEnabled(false);
93 | t.scrollTo(0, 0);
94 | t.setDrawingCacheEnabled(true);
95 | t.buildDrawingCache(true);
96 | }
97 |
98 | private Bitmap getViewBpWithoutBottom(@NonNull View v) {
99 | return getBitmap(v, true);
100 | }
101 |
102 | private Bitmap getViewBp(@NonNull View v) {
103 | return getBitmap(v, false);
104 | }
105 |
106 | private Bitmap getBitmap(@NonNull View v, boolean needRight) {
107 | v.setDrawingCacheEnabled(true);
108 | v.buildDrawingCache();
109 | v.measure(
110 | View.MeasureSpec.makeMeasureSpec(v.getWidth(), View.MeasureSpec.EXACTLY),//
111 | View.MeasureSpec.makeMeasureSpec(v.getHeight(), View.MeasureSpec.EXACTLY));
112 | v.layout((int) v.getX(), (int) v.getY(), (int) v.getX() + v.getMeasuredWidth(),//
113 | (int) v.getY() + v.getMeasuredHeight());
114 | Bitmap bp = Bitmap.createBitmap(v.getDrawingCache(), 0, 0, //
115 | v.getMeasuredWidth() - (needRight ? v.getPaddingRight() : 0), v.getMeasuredHeight());
116 | v.setDrawingCacheEnabled(false);
117 | v.destroyDrawingCache();
118 | return bp;
119 | }
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/viewcapture/src/main/java/com/hd/viewcapture/capture/helper/ScrollCaptureHelper.java:
--------------------------------------------------------------------------------
1 | package com.hd.viewcapture.capture.helper;
2 |
3 | import android.graphics.Bitmap;
4 | import android.view.View;
5 |
6 | /**
7 | * Created by hd on 2018/2/8 .
8 | * Scroll Capture
9 | */
10 | public interface ScrollCaptureHelper {
11 |
12 | /**
13 | * T must have a scrolling attribute
14 | */
15 | Bitmap scrollCapture(T t);
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/viewcapture/src/main/java/com/hd/viewcapture/capture/helper/VerticalScrollCaptureHelper.java:
--------------------------------------------------------------------------------
1 | package com.hd.viewcapture.capture.helper;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Canvas;
5 | import android.support.annotation.NonNull;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | /**
10 | * Created by hd on 2018/2/8 .
11 | * vertical Scroll Capture
12 | */
13 | public class VerticalScrollCaptureHelper implements ScrollCaptureHelper {
14 |
15 | @Override
16 | public Bitmap scrollCapture(T t) {
17 | int currentX = t.getScrollX();
18 | int currentY = t.getScrollY();
19 | try {
20 | enableSomething(t);
21 | return scrollCaptureView(t);
22 | } finally {
23 | restoreSomething(t, currentX, currentY);
24 | }
25 | }
26 |
27 | private Bitmap scrollCaptureView(@NonNull T t) {
28 | Bitmap b = getViewBpWithoutBottom(t);
29 | //the height of the scrollView that is visible
30 | int vh = t.getMeasuredHeight();
31 | //the total height of the scrollView
32 | int th = ((ViewGroup) t).getChildAt(0).getMeasuredHeight();
33 | Bitmap temp;
34 | //the total height is more than one screen
35 | int a = 0;
36 | if (th > vh) {
37 | int w = t.getMeasuredWidth();
38 | //max visible height
39 | int absVh = vh - t.getPaddingTop() - t.getPaddingBottom();
40 | do {
41 | a++;
42 | int restHeight = th - vh;
43 | if (restHeight <= absVh) {
44 | if (a % 2 != 0) {
45 | restHeight = restHeight - t.getPaddingTop() - t.getPaddingBottom();
46 | } else {
47 | restHeight = restHeight + t.getPaddingTop() + t.getPaddingBottom();
48 | }
49 | t.scrollBy(0, restHeight);
50 | vh += restHeight;
51 | temp = getViewBp(t);
52 | } else {
53 | t.scrollBy(0, absVh);
54 | if (a / 2 == 0) {
55 | vh += absVh - t.getPaddingBottom();
56 | } else {
57 | vh += absVh;
58 | }
59 | temp = getViewBp(t);
60 | }
61 | b = mergeBitmap(t, b, vh, temp, w);
62 | } while (vh < th);
63 | }
64 | return b;
65 | }
66 |
67 | @NonNull
68 | private Bitmap mergeBitmap(@NonNull T t, Bitmap b, int vh, Bitmap temp, int w) {
69 | // create the new blank bitmap
70 | Bitmap newbmp = Bitmap.createBitmap(w, vh, Bitmap.Config.RGB_565);
71 | Canvas cv = new Canvas(newbmp);
72 | // draw bg into
73 | cv.drawBitmap(temp, 0, t.getScrollY(), null);
74 | // draw fg into
75 | cv.drawBitmap(b, 0, 0, null);
76 | // save all clip
77 | cv.save(Canvas.ALL_SAVE_FLAG);
78 | // store
79 | cv.restore();
80 | return newbmp;
81 | }
82 |
83 | private void restoreSomething(@NonNull T t, int currentX, int currentY) {
84 | t.scrollTo(currentX, currentY);
85 | t.setVerticalScrollBarEnabled(true);
86 | t.setVerticalFadingEdgeEnabled(true);
87 | t.setDrawingCacheEnabled(false);
88 | t.destroyDrawingCache();
89 | }
90 |
91 | private void enableSomething(@NonNull T t) {
92 | t.setVerticalScrollBarEnabled(false);
93 | t.setVerticalFadingEdgeEnabled(false);
94 | t.scrollTo(0, 0);
95 | t.setDrawingCacheEnabled(true);
96 | t.buildDrawingCache(true);
97 | }
98 |
99 | private Bitmap getViewBpWithoutBottom(@NonNull View v) {
100 | return getBitmap(v, true);
101 | }
102 |
103 | private Bitmap getViewBp(@NonNull View v) {
104 | return getBitmap(v, false);
105 | }
106 |
107 | private Bitmap getBitmap(@NonNull View v, boolean needBottom) {
108 | v.setDrawingCacheEnabled(true);
109 | v.buildDrawingCache();
110 | v.measure(
111 | View.MeasureSpec.makeMeasureSpec(v.getWidth(), View.MeasureSpec.EXACTLY),//
112 | View.MeasureSpec.makeMeasureSpec(v.getHeight(), View.MeasureSpec.EXACTLY));
113 | v.layout((int) v.getX(), (int) v.getY(), (int) v.getX() + v.getMeasuredWidth(),//
114 | (int) v.getY() + v.getMeasuredHeight());
115 | Bitmap bp = Bitmap.createBitmap(v.getDrawingCache(), 0, 0, v.getMeasuredWidth(), //
116 | v.getMeasuredHeight() - (needBottom ? v.getPaddingBottom() : 0));
117 | v.setDrawingCacheEnabled(false);
118 | v.destroyDrawingCache();
119 | return bp;
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/viewcapture/src/main/java/com/hd/viewcapture/capture/helper/WindowCaptureFragment.java:
--------------------------------------------------------------------------------
1 | package com.hd.viewcapture.capture.helper;
2 |
3 | import android.annotation.TargetApi;
4 | import android.app.Activity;
5 | import android.app.Fragment;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.graphics.Bitmap;
9 | import android.graphics.PixelFormat;
10 | import android.hardware.display.DisplayManager;
11 | import android.hardware.display.VirtualDisplay;
12 | import android.media.Image;
13 | import android.media.ImageReader;
14 | import android.media.projection.MediaProjection;
15 | import android.media.projection.MediaProjectionManager;
16 | import android.os.Build;
17 | import android.os.Bundle;
18 | import android.support.annotation.NonNull;
19 | import android.support.annotation.Nullable;
20 | import android.util.DisplayMetrics;
21 | import android.util.Log;
22 |
23 | import com.hd.viewcapture.capture.view.WindowCapture;
24 |
25 | import java.nio.ByteBuffer;
26 |
27 |
28 | /**
29 | * Created by hd on 2018/5/29 .
30 | */
31 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
32 | public class WindowCaptureFragment extends Fragment {
33 |
34 | private final String TAG = WindowCaptureFragment.class.getSimpleName();
35 |
36 | private WindowCapture.WindowCaptureCallback callback;
37 |
38 | private final int REQUEST_MEDIA_PROJECTION = 1;
39 |
40 | private int mScreenDensity;
41 |
42 | private int windowWidth;
43 | private int windowHeight;
44 |
45 | private MediaProjection mMediaProjection;
46 | private VirtualDisplay mVirtualDisplay;
47 | private MediaProjectionManager mMediaProjectionManager;
48 | private ImageReader mImageReader;
49 |
50 | @Override
51 | public void onCreate(@Nullable Bundle savedInstanceState) {
52 | super.onCreate(savedInstanceState);
53 | DisplayMetrics metrics = new DisplayMetrics();
54 | getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
55 | mScreenDensity = metrics.densityDpi;
56 | windowWidth = metrics.widthPixels;
57 | windowHeight = metrics.heightPixels;
58 | mImageReader = ImageReader.newInstance(windowWidth, windowHeight, PixelFormat.RGBA_8888, 2);
59 | mMediaProjectionManager = (MediaProjectionManager) getActivity().getSystemService(Context.MEDIA_PROJECTION_SERVICE);
60 | }
61 |
62 | public void prepare(@NonNull WindowCapture.WindowCaptureCallback callback) {
63 | this.callback = callback;
64 | if (mMediaProjectionManager != null) {
65 | startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
66 | } else {
67 | callback.report(false);
68 | }
69 | }
70 |
71 | @Override
72 | public void onActivityResult(int requestCode, int resultCode, Intent data) {
73 | super.onActivityResult(requestCode, resultCode, data);
74 | if (requestCode == REQUEST_MEDIA_PROJECTION) {
75 | if (resultCode != Activity.RESULT_OK) {
76 | Log.i(TAG, "User cancelled");
77 | callback.report(false);
78 | return;
79 | }
80 | Log.i(TAG, "Starting screen capture");
81 | mMediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data);
82 | callback.report(true);
83 | }
84 | }
85 |
86 | public Bitmap capture() {
87 | try {
88 | mVirtualDisplay = mMediaProjection.createVirtualDisplay(TAG, windowWidth, windowHeight, mScreenDensity, //
89 | DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,//
90 | mImageReader.getSurface(), null, null);
91 | Log.i(TAG, "screen capture completed");
92 | try {
93 | Thread.sleep(500);
94 | } catch (InterruptedException e) {
95 | e.printStackTrace();
96 | }
97 | return createBitmap();
98 | } finally {
99 | release();
100 | }
101 | }
102 |
103 | private Bitmap createBitmap() {
104 | Image image = mImageReader.acquireLatestImage();
105 | int width = image.getWidth();
106 | int height = image.getHeight();
107 | final Image.Plane[] planes = image.getPlanes();
108 | final ByteBuffer buffer = planes[0].getBuffer();
109 | int pixelStride = planes[0].getPixelStride();
110 | int rowStride = planes[0].getRowStride();
111 | int rowPadding = rowStride - pixelStride * width;
112 | Bitmap bitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888);
113 | bitmap.copyPixelsFromBuffer(buffer);
114 | bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height);
115 | image.close();
116 | return bitmap;
117 | }
118 |
119 | private void release() {
120 | if (mMediaProjection != null) {
121 | mMediaProjection.stop();
122 | mMediaProjection = null;
123 | }
124 | if (mVirtualDisplay != null) {
125 | mVirtualDisplay.release();
126 | mVirtualDisplay = null;
127 | }
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/viewcapture/src/main/java/com/hd/viewcapture/capture/view/DefaultViewCapture.java:
--------------------------------------------------------------------------------
1 | package com.hd.viewcapture.capture.view;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Canvas;
5 | import android.support.annotation.NonNull;
6 | import android.view.View;
7 |
8 | import com.hd.viewcapture.capture.Capture;
9 |
10 | /**
11 | * Created by hd on 2018/2/6 .
12 | * View Capture
13 | */
14 | public class DefaultViewCapture extends Capture {
15 |
16 | @Override
17 | public Bitmap capture(@NonNull View view) {
18 | Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
19 | Canvas canvas = new Canvas(bitmap);
20 | view.draw(canvas);
21 | canvas.setBitmap(null);
22 | report(bitmap);
23 | return bitmap;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/viewcapture/src/main/java/com/hd/viewcapture/capture/view/HorizontalScrollViewCapture.java:
--------------------------------------------------------------------------------
1 | package com.hd.viewcapture.capture.view;
2 |
3 | import android.graphics.Bitmap;
4 | import android.support.annotation.NonNull;
5 | import android.widget.HorizontalScrollView;
6 |
7 | import com.hd.viewcapture.capture.Capture;
8 | import com.hd.viewcapture.capture.helper.HorizontalScrollCaptureHelper;
9 |
10 | /**
11 | * Created by hd on 2018/2/6 .
12 | * HorizontalScrollView Capture
13 | */
14 | public class HorizontalScrollViewCapture extends Capture {
15 | @Override
16 | public Bitmap capture(@NonNull HorizontalScrollView horizontalScrollView) {
17 | Bitmap bitmap = new HorizontalScrollCaptureHelper().scrollCapture(horizontalScrollView);
18 | report(bitmap);
19 | return bitmap;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/viewcapture/src/main/java/com/hd/viewcapture/capture/view/ListViewCapture.java:
--------------------------------------------------------------------------------
1 | package com.hd.viewcapture.capture.view;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 | import android.graphics.Rect;
7 | import android.graphics.drawable.Drawable;
8 | import android.support.annotation.NonNull;
9 | import android.view.View;
10 | import android.widget.ListAdapter;
11 | import android.widget.ListView;
12 |
13 | import com.hd.viewcapture.capture.Capture;
14 |
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | /**
19 | * Created by hd on 2018/2/6 .
20 | * ListView Capture
21 | */
22 | public class ListViewCapture extends Capture {
23 | @Override
24 | public Bitmap capture(@NonNull ListView listView) {
25 | List viewList = new ArrayList<>();
26 | try {
27 | ListAdapter adapter = listView.getAdapter();
28 | Drawable dividerDrawable = listView.getDivider();
29 | Drawable backgroundDrawable = listView.getBackground();
30 | int dividerHeight = listView.getDividerHeight();
31 | int itemsCount = adapter.getCount();
32 | int allHeight = listView.getPaddingTop() + listView.getPaddingBottom();
33 | int allWidth = listView.getMeasuredWidth() + listView.getPaddingLeft() + listView.getPaddingRight();
34 | for (int i = 0; i < adapter.getCount(); i++) {
35 | View childView = adapter.getView(i, null, listView);
36 | childView.measure(
37 | View.MeasureSpec.makeMeasureSpec(listView.getWidth(), View.MeasureSpec.EXACTLY),//
38 | View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
39 | childView.layout(0, 0, childView.getMeasuredWidth(), childView.getMeasuredHeight());
40 | childView.setDrawingCacheEnabled(true);
41 | childView.buildDrawingCache();
42 | viewList.add(childView);
43 | allHeight += childView.getMeasuredHeight();
44 | }
45 | allHeight += (itemsCount - 1) * dividerHeight;
46 | Bitmap bigBitmap = Bitmap.createBitmap(allWidth, allHeight, Bitmap.Config.RGB_565);
47 | Canvas bigCanvas = new Canvas(bigBitmap);
48 | Paint paint = new Paint();
49 | int iHeight = listView.getPaddingTop();
50 | final Rect bounds = new Rect();
51 | bounds.set(0, 0, allWidth, allHeight);
52 | backgroundDrawable.setBounds(bounds);
53 | backgroundDrawable.draw(bigCanvas);
54 | for (int i = 0; i < viewList.size(); i++) {
55 | View view = viewList.get(i);
56 | Bitmap bmp = view.getDrawingCache();
57 | bigCanvas.drawBitmap(bmp, listView.getPaddingLeft(), iHeight, paint);
58 | iHeight += bmp.getHeight();
59 | if (i < viewList.size() - 1 && dividerHeight > 0 && dividerDrawable != null) {
60 | bounds.set(0, iHeight, allWidth, iHeight + dividerHeight);
61 | dividerDrawable.setBounds(bounds);
62 | dividerDrawable.draw(bigCanvas);
63 | iHeight += dividerHeight;
64 | }
65 | view.setDrawingCacheEnabled(false);
66 | view.destroyDrawingCache();
67 | bmp.recycle();
68 | bmp = null;
69 | }
70 | report(bigBitmap);
71 | return bigBitmap;
72 | } finally {
73 | viewList.clear();
74 | viewList = null;
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/viewcapture/src/main/java/com/hd/viewcapture/capture/view/RecyclerViewCapture.java:
--------------------------------------------------------------------------------
1 | package com.hd.viewcapture.capture.view;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 | import android.graphics.Rect;
7 | import android.graphics.drawable.Drawable;
8 | import android.support.annotation.NonNull;
9 | import android.support.v7.widget.RecyclerView;
10 | import android.util.LruCache;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 |
14 | import com.hd.viewcapture.capture.Capture;
15 |
16 | /**
17 | * Created by hd on 2018/2/6 .
18 | * RecyclerView capture
19 | */
20 | public class RecyclerViewCapture extends Capture {
21 |
22 | @Override
23 | public Bitmap capture(@NonNull RecyclerView recyclerView) {
24 | RecyclerView.Adapter adapter = recyclerView.getAdapter();
25 | Bitmap bigBitmap = null;
26 | if (adapter != null) {
27 | int size = adapter.getItemCount();
28 | int height = recyclerView.getPaddingTop() + recyclerView.getPaddingBottom();
29 | final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
30 | // Use 1/8th of the available memory for this memory cache.
31 | final int cacheSize = maxMemory / 8;
32 | LruCache viewCache = new LruCache<>(cacheSize);
33 | int allWidth = recyclerView.getMeasuredWidth() + recyclerView.getPaddingLeft() + recyclerView.getPaddingRight();
34 | for (int i = 0; i < size; i++) {
35 | RecyclerView.ViewHolder holder = adapter.createViewHolder(recyclerView, adapter.getItemViewType(i));
36 | adapter.onBindViewHolder(holder, i);
37 | holder.itemView.measure(
38 | View.MeasureSpec.makeMeasureSpec(recyclerView.getWidth(), View.MeasureSpec.EXACTLY), //
39 | View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
40 | holder.itemView.layout(0, 0, holder.itemView.getMeasuredWidth(), holder.itemView.getMeasuredHeight());
41 | holder.itemView.setDrawingCacheEnabled(true);
42 | holder.itemView.buildDrawingCache();
43 | viewCache.put(String.valueOf(i), holder.itemView);
44 | int itemHeight = holder.itemView.getMeasuredHeight();
45 | int[] margin = getMargin(holder.itemView);
46 | height += itemHeight + margin[0] + margin[1];
47 | }
48 | bigBitmap = Bitmap.createBitmap(allWidth, height, Bitmap.Config.RGB_565);
49 | Canvas bigCanvas = new Canvas(bigBitmap);
50 | Drawable lBackground = recyclerView.getBackground();
51 | final Rect bounds = new Rect();
52 | bounds.set(0, 0, allWidth, height);
53 | lBackground.setBounds(bounds);
54 | lBackground.draw(bigCanvas);
55 | Paint paint = new Paint();
56 | int iHeight = recyclerView.getPaddingTop();
57 | for (int i = 0; i < size; i++) {
58 | View view = viewCache.get(String.valueOf(i));
59 | int[] margin = getMargin(view);
60 | int topMargin = margin[0];
61 | int bottomMargin = +margin[1];
62 | Bitmap bitmap = view.getDrawingCache();
63 | bigCanvas.drawBitmap(bitmap, recyclerView.getPaddingLeft(), iHeight + topMargin, paint);
64 | iHeight += view.getHeight() + topMargin + bottomMargin;
65 | view.setDrawingCacheEnabled(false);
66 | view.destroyDrawingCache();
67 | bitmap.recycle();
68 | bitmap = null;
69 | }
70 | }
71 | report(bigBitmap);
72 | return bigBitmap;
73 | }
74 |
75 | private int[] getMargin(View itemView) {
76 | ViewGroup.MarginLayoutParams marginLayoutParams = (ViewGroup.MarginLayoutParams) itemView.getLayoutParams();
77 | return new int[]{marginLayoutParams.topMargin, marginLayoutParams.topMargin};
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/viewcapture/src/main/java/com/hd/viewcapture/capture/view/ScrollViewCapture.java:
--------------------------------------------------------------------------------
1 | package com.hd.viewcapture.capture.view;
2 |
3 | import android.graphics.Bitmap;
4 | import android.support.annotation.NonNull;
5 | import android.widget.ScrollView;
6 |
7 | import com.hd.viewcapture.capture.Capture;
8 | import com.hd.viewcapture.capture.helper.VerticalScrollCaptureHelper;
9 |
10 | /**
11 | * Created by hd on 2018/2/6 .
12 | * scrollview capture
13 | */
14 | public class ScrollViewCapture extends Capture {
15 | @Override
16 | public Bitmap capture(@NonNull ScrollView scrollView) {
17 | Bitmap bitmap = new VerticalScrollCaptureHelper().scrollCapture(scrollView);
18 | report(bitmap);
19 | return bitmap;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/viewcapture/src/main/java/com/hd/viewcapture/capture/view/WebViewCapture.java:
--------------------------------------------------------------------------------
1 | package com.hd.viewcapture.capture.view;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.graphics.Bitmap;
5 | import android.graphics.Canvas;
6 | import android.graphics.Paint;
7 | import android.graphics.Picture;
8 | import android.os.Build;
9 | import android.support.annotation.NonNull;
10 | import android.view.View;
11 | import android.webkit.WebView;
12 |
13 | import com.hd.viewcapture.capture.Capture;
14 |
15 | /**
16 | * Created by hd on 2018/2/6 .
17 | * WebView Capture
18 | */
19 | public class WebViewCapture extends Capture {
20 |
21 | @Override
22 | public Bitmap capture(@NonNull WebView webView) {
23 | Bitmap bitmap;
24 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
25 | bitmap = captureWebView(webView);
26 | } else {
27 | bitmap = captureWebView2(webView);
28 | }
29 | report(bitmap);
30 | return bitmap;
31 | }
32 |
33 | private Bitmap captureWebView(WebView webView) {
34 | Picture picture = webView.capturePicture();
35 | int width = picture.getWidth();
36 | int height = picture.getHeight();
37 | if (width > 0 && height > 0) {
38 | Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
39 | Canvas canvas = new Canvas(bitmap);
40 | picture.draw(canvas);
41 | return bitmap;
42 | }
43 | return null;
44 | }
45 |
46 | @SuppressLint("WrongCall")
47 | private Bitmap captureWebView2(@NonNull final WebView view) {
48 | openCache(view);
49 | int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
50 | view.measure(measureSpec, measureSpec);
51 | if (view.getMeasuredWidth() <= 0 || view.getMeasuredHeight() <= 0) {
52 | return null;
53 | }
54 | Bitmap bm;
55 | try {
56 | bm = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
57 | } catch (OutOfMemoryError e) {
58 | System.gc();
59 | try {
60 | bm = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.RGB_565);
61 | } catch (OutOfMemoryError ee) {
62 | closeCache(view);
63 | return captureWebView3(view);
64 | }
65 | }
66 | Canvas bigCanvas = new Canvas(bm);
67 | Paint paint = new Paint();
68 | int iHeight = bm.getHeight();
69 | bigCanvas.drawBitmap(bm, 0, iHeight, paint);
70 | view.draw(bigCanvas);
71 | closeCache(view);
72 | return bm;
73 | }
74 |
75 | private Bitmap captureWebView3(WebView wv) {
76 | try {
77 | float scale = wv.getScale();
78 | int height = (int) (wv.getContentHeight() * scale + 0.5);
79 | Bitmap bitmap = Bitmap.createBitmap(wv.getWidth(), height, Bitmap.Config.ARGB_8888);
80 | Canvas canvas = new Canvas(bitmap);
81 | wv.draw(canvas);
82 | return bitmap;
83 | } catch (Exception e) {
84 | try {
85 | openCache(wv);
86 | return wv.getDrawingCache();
87 | } finally {
88 | closeCache(wv);
89 | }
90 | }
91 | }
92 |
93 | private void openCache(@NonNull WebView view) {
94 | view.setDrawingCacheEnabled(true);
95 | view.buildDrawingCache();
96 | }
97 |
98 | private void closeCache(@NonNull WebView view) {
99 | view.setDrawingCacheEnabled(false);
100 | view.destroyDrawingCache();
101 | }
102 |
103 | }
104 |
--------------------------------------------------------------------------------
/viewcapture/src/main/java/com/hd/viewcapture/capture/view/WindowCapture.java:
--------------------------------------------------------------------------------
1 | package com.hd.viewcapture.capture.view;
2 |
3 | import android.annotation.TargetApi;
4 | import android.app.Activity;
5 | import android.app.FragmentManager;
6 | import android.graphics.Bitmap;
7 | import android.os.Build;
8 | import android.support.annotation.NonNull;
9 |
10 | import com.hd.viewcapture.capture.Capture;
11 | import com.hd.viewcapture.capture.helper.WindowCaptureFragment;
12 |
13 |
14 | /**
15 | * Created by hd on 2018/5/29 .
16 | */
17 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
18 | public class WindowCapture extends Capture {
19 |
20 | private final String TAG = "Window-Capture";
21 |
22 | private WindowCaptureFragment windowCaptureFragment;
23 |
24 | public interface WindowCaptureCallback {
25 |
26 | void report(boolean state);
27 | }
28 |
29 | private WindowCaptureFragment getWindowCaptureFragment(@NonNull Activity activity) {
30 | WindowCaptureFragment windowCaptureFragment = findScreenCaptureFragment(activity);
31 | boolean isNewInstance = windowCaptureFragment == null;
32 | if (isNewInstance) {
33 | windowCaptureFragment = new WindowCaptureFragment();
34 | FragmentManager fragmentManager = activity.getFragmentManager();
35 | fragmentManager.beginTransaction().add(windowCaptureFragment, TAG).commitAllowingStateLoss();
36 | fragmentManager.executePendingTransactions();
37 | }
38 | return windowCaptureFragment;
39 | }
40 |
41 | private WindowCaptureFragment findScreenCaptureFragment(@NonNull Activity activity) {
42 | return (WindowCaptureFragment) activity.getFragmentManager().findFragmentByTag(TAG);
43 | }
44 |
45 | @Override
46 | public Bitmap capture(@NonNull Activity activity) {
47 | windowCaptureFragment = getWindowCaptureFragment(activity);
48 | windowCaptureFragment.prepare(new WindowCaptureCallback() {
49 | @Override
50 | public void report(boolean state) {
51 | if (state) {
52 | WindowCapture.this.report(windowCaptureFragment.capture());
53 | } else {
54 | WindowCapture.this.report(null);
55 | }
56 | }
57 | });
58 | return null;
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/viewcapture/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | viewcapture
3 |
4 |
--------------------------------------------------------------------------------
/viewcapture/src/test/java/com/hd/viewcapture/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.hd.viewcapture;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------