In android API 28 view.getDrawingCache()
has been deprecated. Is there any newer solution to generate a Bitmap of a particular view in android.
view.getDrawingCache() is deprecated in Android API 28
Asked Answered
I have found a way to use PixelCopy API for retrieving the view as a Bitmap. Used Kotlin
fun getBitmapFromView(view: View, activity: Activity, callback: (Bitmap) -> Unit) {
activity.window?.let { window ->
val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
val locationOfViewInWindow = IntArray(2)
view.getLocationInWindow(locationOfViewInWindow)
try {
PixelCopy.request(window, Rect(locationOfViewInWindow[0], locationOfViewInWindow[1], locationOfViewInWindow[0] + view.width, locationOfViewInWindow[1] + view.height), bitmap, { copyResult ->
if (copyResult == PixelCopy.SUCCESS) {
callback(bitmap)
}
// possible to handle other result codes ...
}, Handler())
} catch (e: IllegalArgumentException) {
// PixelCopy may throw IllegalArgumentException, make sure to handle it
e.printStackTrace()
}
}
}
ref –
Complicated
Why does Google always have to complicate things? I want the bitmap the same time I'm calling the method not later on in the future using callbacks. –
Sanderlin
@Sanderlin I found this today which I'm going to use instead. –
Complicated
PixelCopy
requires API Level 26 and above. If you want compatability, for older API level, use the solution posted by @daka. –
Rescissory @daka you can use link this library. It handles all stuffs for saving an image of a view. –
Exeter
A better and optimised solution would be "view.drawToBitmap()" –
Minute
Two ways to get bitmap of view
- Using Canvas
- Using Pixel Api
Canvas Java
Bitmap getBitmapFromView(View view) {
Bitmap bitmap = Bitmap.createBitmap(
view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888
);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
Bitmap getBitmapFromView(View view,int defaultColor) {
Bitmap bitmap = Bitmap.createBitmap(
view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888
);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(defaultColor);
view.draw(canvas);
return bitmap;
}
Canvas Kotlin
fun getBitmapFromView(view: View): Bitmap {
val bitmap = Bitmap.createBitmap(
view.width, view.height, Bitmap.Config.ARGB_8888
)
val canvas = Canvas(bitmap)
view.draw(canvas)
return bitmap
}
fun getBitmapFromView(view: View, defaultColor: Int): Bitmap {
val bitmap = Bitmap.createBitmap(
view.width, view.height, Bitmap.Config.ARGB_8888
)
val canvas = Canvas(bitmap)
canvas.drawColor(defaultColor)
view.draw(canvas)
return bitmap
}
Example
//@param rootView is View object which you want to get bitmap
Bitmap bitmap = getBitmapFromView(rootView);
Bitmap bitmapColored = getBitmapFromView(rootView,Color.WHITE);
PixelCopy Api
https://mcmap.net/q/331967/-view-getdrawingcache-is-deprecated-in-android-api-28
fun getBitmapFromView(view: View, activity: Activity, callback: (Bitmap) -> Unit) {
activity.window?.let { window ->
val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
val locationOfViewInWindow = IntArray(2)
view.getLocationInWindow(locationOfViewInWindow)
try {
PixelCopy.request(window, Rect(locationOfViewInWindow[0], locationOfViewInWindow[1], locationOfViewInWindow[0] + view.width, locationOfViewInWindow[1] + view.height), bitmap, { copyResult ->
if (copyResult == PixelCopy.SUCCESS) {
callback(bitmap)
}
// possible to handle other result codes ...
}, Handler())
} catch (e: IllegalArgumentException) {
// PixelCopy may throw IllegalArgumentException, make sure to handle it
e.printStackTrace()
}
}
}
For More See About
how can I get portion of view. createBitmap seems to take only width and height, looking for x,y,width,height –
Probable
@Probable user this
Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height)
–
Pasargadae and how do you get source now. Bcz view.getDrawingCache() is deprecated which was returning bitmap. –
Probable
@Probable first use this method to get bitmap of view the modify as u need –
Pasargadae
kotlin has a View.drawToBitmap extension function, which takes scrollX/Y into consideration –
Diminish
I have found a way to use PixelCopy API for retrieving the view as a Bitmap. Used Kotlin
fun getBitmapFromView(view: View, activity: Activity, callback: (Bitmap) -> Unit) {
activity.window?.let { window ->
val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
val locationOfViewInWindow = IntArray(2)
view.getLocationInWindow(locationOfViewInWindow)
try {
PixelCopy.request(window, Rect(locationOfViewInWindow[0], locationOfViewInWindow[1], locationOfViewInWindow[0] + view.width, locationOfViewInWindow[1] + view.height), bitmap, { copyResult ->
if (copyResult == PixelCopy.SUCCESS) {
callback(bitmap)
}
// possible to handle other result codes ...
}, Handler())
} catch (e: IllegalArgumentException) {
// PixelCopy may throw IllegalArgumentException, make sure to handle it
e.printStackTrace()
}
}
}
ref –
Complicated
Why does Google always have to complicate things? I want the bitmap the same time I'm calling the method not later on in the future using callbacks. –
Sanderlin
@Sanderlin I found this today which I'm going to use instead. –
Complicated
PixelCopy
requires API Level 26 and above. If you want compatability, for older API level, use the solution posted by @daka. –
Rescissory @daka you can use link this library. It handles all stuffs for saving an image of a view. –
Exeter
A better and optimised solution would be "view.drawToBitmap()" –
Minute
Try this:
private fun convertViewToDrawable(view: View): Bitmap {
val spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
view.measure(spec, spec)
view.layout(0, 0, view.measuredWidth, view.measuredHeight)
val b = Bitmap.createBitmap(view.measuredWidth, view.measuredHeight,
Bitmap.Config.ARGB_8888)
val c = Canvas(b)
c.translate((-view.scrollX).toFloat(), (-view.scrollY).toFloat())
view.draw(c)
return b
}
What's the need of translate, and of scrolling values? –
Dodona
Without it, if the view is scrolled, the part of the view that gets written to the bitmap will not match the part of the view that is actually visible. –
Toile
As of the official documentation getDrawingCache() you should use the PixelCopy api.
Do I need to use SurfaceView to use PixelCopy(). Cause in android documentation it sayes "pixel copy requests to allow for copy operations from Surface to Bitmap". –
Exeter
add an example of pixelCopy() to capture bitmap of view –
Pasargadae
@Ashvinsolanki please checkout my answer. It works on. –
Exeter
how to use: medium.com/@hiteshkrsahu/… –
Trahurn
The use of PixelCopy is not necessarily "should". The docs only recommends using it for UI feedback report and unit tests. –
Trevelyan
much precise code..
private fun convertViewToDrawable(view: View): Bitmap {
val b = Bitmap.createBitmap(view.measuredWidth, view.measuredHeight,
Bitmap.Config.ARGB_8888)
val c = Canvas(b)
c.translate((-view.scrollX).toFloat(), (-view.scrollY).toFloat())
view.draw(c)
return b
}
Why the need of translate, and of scrolling values? –
Dodona
Some other kotlin code (ScrollView case)
val ScrollView.bitmap: Bitmap
get() {
val bitmap = Bitmap.createBitmap(width, getChildAt(0).height, Bitmap.Config.RGB_565)
with(Canvas(bitmap)) {
val background = background
if (background != null) {
background.draw(this)
} else {
drawColor(Color.WHITE)
}
draw(this)
}
return bitmap
}
bitmap = view.drawToBitmap()
val pixel = bitmap.getpixel(x,y)
While this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply. –
Pediatrics
Kotlin code with view inflation:
fun getBitmapFromView(layoutInflater: LayoutInflater): Bitmap =
layoutInflater.inflate(R.layout.layoutID, null).run {
//Bind data If you needed Example - [findViewById<TextView>(R.id.viewId).text = data]
measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
layout(0, 0, measuredWidth, measuredHeight)
val bitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
draw(canvas)
bitmap
}
layoutInflater can be retrieved like,
Inside activity or fragment -
this.layoutInflaterOutside activity or fragment -
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
© 2022 - 2024 — McMap. All rights reserved.