Talking about Android Screenshot and Specifying View to Generate Screenshot
- 2021-12-13 09:28:21
- OfStack
Screenshot of the current page (capturing the whole screen)
Take a screenshot of the current Activity page, which can be cached through decorView at the bottom of the form, and then generate a picture according to this cached object. Some need not need the status bar, you can also specify the width and height of the generated picture, and remove the status bar.
/**
* Capture a screenshot of the current form, according to the [isShowStatusBar] Determines whether to include the status bar of the current form
* The principle is to get the current form decorView Generate pictures from the cache of
*/
fun captureWindow(activity: Activity, isShowStatusBar: Boolean): Bitmap? {
// Object of the current form View Object
val view = activity.window.decorView
view.isDrawingCacheEnabled = true
// Generate cache
view.buildDrawingCache()
val bitmap = if (isShowStatusBar) {
// Draws the entire form, including the status bar
Bitmap.createBitmap(view.drawingCache, 0, 0, view.measuredWidth, view.measuredHeight)
} else {
// Get the height of the status bar
val rect = Rect()
view.getWindowVisibleDisplayFrame(rect)
val display = activity.windowManager.defaultDisplay
// Subtract the height of the status bar
Bitmap.createBitmap(view.drawingCache, 0,
rect.top, display.width, display.height - rect.top)
}
view.isDrawingCacheEnabled = false
view.destroyDrawingCache()
return bitmap
}
Intercept commonly used View
Be sure that View has been drawn before interception, so be careful to use post method to ensure that View is drawn. Some shared screenshot pages are not in the UI style currently displayed to users, so a container can be hidden in the current layout to store screenshots, and this container is not displayed to users.
/**
* View Has been shown on the interface, and can be obtained directly View Cache of
* Right View Generate after measurement and layout View Cache of
* View Is a fixed-size View , including TextView,ImageView,LinearLayout,FrameLayout,RelativeLayout Etc
* @param view Intercepted View,View Must have a fixed size, otherwise drawingCache Return null
* @return Generated Bitmap
*/
fun captureView(view: View): Bitmap? {
view.isDrawingCacheEnabled = true
view.buildDrawingCache()
// Re-measurement 1 Pass View Width and height of
view.measure(View.MeasureSpec.makeMeasureSpec(view.width, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(view.height, View.MeasureSpec.EXACTLY))
// Determine View Location of
view.layout(view.x.toInt(), view.y.toInt(), view.x.toInt() + view.measuredWidth,
view.y.toInt() + view.measuredHeight)
// Generate View Width and height 1 Like Bitmap
val bitmap = Bitmap.createBitmap(view.drawingCache, 0, 0, view.measuredWidth,
view.measuredHeight)
view.isDrawingCacheEnabled = false
view.destroyDrawingCache()
return bitmap
}
Intercept ScrollView
The difficulty of ScrollView screenshot is that the height of ScrollView is uncertain. If the height can be determined, you can use the cache of ScrollView to generate pictures. ScrollView has only one child View, so the height of ScrollView can be determined only by measuring the child View and obtaining the height of the child View.
/**
* Interception ScrollerView
* The principle is to get scrollView Son of View The height of, and then create 1 Sub View Wide and high canvas, which will ScrollView Draw on a canvas
* @param scrollView Control
* @return Return to the after the screenshot Bitmap
*/
fun captureScrollView(scrollView: ScrollView): Bitmap? {
var h = 0
for (i in 0 until scrollView.childCount) {
val childView = scrollView.getChildAt(i)
// Acquirer View The height of
h += childView.height
// Set the background color to avoid the background color not set in the layout and the background of the cut-off image is black
childView.setBackgroundColor(Color.parseColor("#FFFFFF"))
}
val bitmap = createBitmap(scrollView.width, h)
val canvas = Canvas(bitmap)
// Will ScrollView Draw on a canvas
scrollView.draw(canvas)
return bitmap
}
Intercept ListView
The principle of ListView screenshot is to obtain Bitmap object of every sub-View, then use Paint to splice screenshots of sub-View onto Canvas according to the height of sub-View, and finally generate a screenshot containing all sub-View.
/**
* Interception ListView
* Principle: Get every 1 Sub View , will son View Generated bitmap Save into the collection and accumulate ListView Height
* After the traversal is complete, create 1 A ListView A canvas of the size of the collection, and the Bitmap Draw to canvas
* @param listView Screenshot control object
* @return Generated screenshot object
*/
fun captureListView(listView: ListView): Bitmap? {
val adapter = listView.adapter
val itemCount = adapter.count
var allitemsheight = 0
val bitmaps = ArrayList<Bitmap>()
for (i in 0 until itemCount) {
// Gets every 1 Sub View
val childView = adapter.getView(i, null, listView)
// Measure width and height
childView.measure(
View.MeasureSpec.makeMeasureSpec(listView.width, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED))
// Layout position
childView.layout(0, 0, childView.measuredWidth, childView.measuredHeight)
// Set the background color to avoid black
childView.setBackgroundColor(Color.parseColor("#FFFFFF"))
childView.isDrawingCacheEnabled = true
// Generate cache
childView.buildDrawingCache()
// Will each 1 A View Add screenshots of to the collection
bitmaps.add(childView.drawingCache)
// Overlay screenshot height
allitemsheight += childView.measuredHeight
}
// Create and ListView Width and height 1 A kind of canvas
val bitmap = createBitmap(listView.measuredWidth, allitemsheight)
val canvas = Canvas(bitmap)
val paint = Paint()
var iHeight = 0f
for (i in bitmaps.indices) {
val bmp: Bitmap = bitmaps[i]
// Will each 1 Generated bitmap Draw on a canvas
canvas.drawBitmap(bmp, 0f, iHeight, paint)
iHeight += bmp.height
bmp.recycle()
}
return bitmap
}
Intercept RecyclerView
RecyclerView screenshot and ListView screenshot have the same principle, both of which splice the screenshots of sub-View, and finally generate a large screenshot.
/**
* Interception RecyclerView
* Principle and ListView The set is 1 Sample, get every 1 A Holder The screenshots of are put into the collection, and the final system is unified 1 Draw to Bitmap Upper
* @param recyclerView  Control to take a screenshot of
* @return Generated screenshots
*/
fun captureRecyclerView(recyclerView: RecyclerView): Bitmap? {
val adapter = recyclerView.adapter
var bigBitmap: Bitmap? = null
if (adapter != null) {
val size = adapter.itemCount
var height = 0
val paint = Paint()
var iHeight = 0
val maxMemory = (Runtime.getRuntime().maxMemory() / 1024).toInt()
// Use 1/8th of the available memory for this memory cache.
val cacheSize = maxMemory / 8
val bitmapCache = LruCache<String, Bitmap>(cacheSize)
for (i in 0 until size) {
val holder = adapter.createViewHolder(recyclerView, adapter.getItemViewType(i))
adapter.onBindViewHolder(holder, i)
holder.itemView.measure(
View.MeasureSpec.makeMeasureSpec(recyclerView.width, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED))
holder.itemView.layout(0, 0, holder.itemView.measuredWidth,
holder.itemView.measuredHeight)
holder.itemView.setBackgroundColor(Color.parseColor("#FFFFFF"))
holder.itemView.isDrawingCacheEnabled = true
holder.itemView.buildDrawingCache()
val drawingCache = holder.itemView.drawingCache
if (drawingCache != null) {
bitmapCache.put(i.toString(), drawingCache)
}
height += holder.itemView.measuredHeight
}
bigBitmap = createBitmap(recyclerView.measuredWidth, height)
val bigCanvas = Canvas(bigBitmap!!)
val lBackground = recyclerView.background
if (lBackground is ColorDrawable) {
val lColor = lBackground.color
bigCanvas.drawColor(lColor)
}
for (i in 0 until size) {
val bitmap = bitmapCache.get(i.toString())
bigCanvas.drawBitmap(bitmap, 0f, iHeight.toFloat(), paint)
iHeight += bitmap.height
bitmap.recycle()
}
}
return bigBitmap
}
Intercept WebView
WebView can load very long and complicated pages, so it is easy to overflow memory for screenshots, but there will be no big pictures to share for 1-like needs, so only simple screenshots will be made here.
/**
* Interception WebView , including WebView The entire length of
* In WebView Before rendering, add the following code to open Html Cache, or the screen shot will be blank
* if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
* WebView.enableSlowWholeDocumentDraw()
* }
* WebView Screenshots of are prone to memory overflow problems because WebView You can load a lot of content, resulting in a very long picture. Create a Bitmap Time is easy OOM
*/
fun captureWebView(webView: WebView): Bitmap? {
//  Recall WebView Adj. measure Method to measure the actual situation View Set the measurement mode to UNSPECIFIED Pattern means that you can get as much space as you need.)
webView.measure(View.MeasureSpec.makeMeasureSpec(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED))
//  Call layout Method to set the layout (using the newly measured size)
webView.layout(0, 0, webView.measuredWidth, webView.measuredHeight)
//  Open WebView Cache of ( When this switch is turned on, the next call is made getDrawingCache() Method will put view Draw to 1 A bitmap Upper )
webView.isDrawingCacheEnabled = true
//  Force the drawing cache (must be in the setDrawingCacheEnabled(true) It can only be called after, or it needs to be called manually destroyDrawingCache() Clear cache)
webView.buildDrawingCache()
val bitmap = createBitmap(webView.measuredWidth, webView.measuredHeight)
//  Has picture Create for the background 1 Canvas
val canvas = Canvas(bitmap) // Width and height of canvas WebView The web page of remains 1 To
val paint = Paint()
//  Set the fixed point position of the brush, that is, the upper left corner
canvas.drawBitmap(bitmap, 0f, webView.measuredHeight * 1f, paint)
//  Will WebView Draw on the drawing board just created
webView.draw(canvas)
webView.isDrawingCacheEnabled = false
webView.destroyDrawingCache()
return bitmap
}
Basically, View can take screenshots, but OOM is easy to take screenshots for controls like WebView, which can load long and complex pages, so we should consider what controls to use for screenshots. The above code can be used for pro-testing.
The above is the details of Android screenshots and specifying View screenshots. For more information about Android screenshots and specifying View screenshots, please pay attention to other related articles on this site!