view.getDrawingCache() is deprecated in Android API 28
Asked Answered
E

8

52

In android API 28 view.getDrawingCache() has been deprecated. Is there any newer solution to generate a Bitmap of a particular view in android.

Exeter answered 4/10, 2018 at 8:14 Comment(0)
E
14

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()
        }
    }
}
Exeter answered 25/10, 2018 at 9:10 Comment(6)
refComplicated
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
P
82

Two ways to get bitmap of view

  1. Using Canvas
  2. 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

Bitmaps

Canvas

Pasargadae answered 20/10, 2018 at 12:32 Comment(5)
how can I get portion of view. createBitmap seems to take only width and height, looking for x,y,width,heightProbable
@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 needPasargadae
kotlin has a View.drawToBitmap extension function, which takes scrollX/Y into considerationDiminish
E
14

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()
        }
    }
}
Exeter answered 25/10, 2018 at 9:10 Comment(6)
refComplicated
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
D
3

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
}
Dictator answered 20/6, 2019 at 11:6 Comment(2)
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
I
2

As of the official documentation getDrawingCache() you should use the PixelCopy api.

Intentional answered 4/10, 2018 at 8:16 Comment(5)
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 viewPasargadae
@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
H
1

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
    }
Homily answered 24/9, 2019 at 17:25 Comment(1)
Why the need of translate, and of scrolling values?Dodona
S
0

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
}
Secrest answered 18/6, 2020 at 8:32 Comment(0)
A
0
bitmap = view.drawToBitmap()
val pixel = bitmap.getpixel(x,y)
Azpurua answered 25/5, 2022 at 5:12 Comment(1)
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
T
0

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,

  1. Inside activity or fragment -
    this.layoutInflater

  2. Outside activity or fragment -
    val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater

Tullus answered 22/9, 2022 at 12:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.