48

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

Ashvin solanki
  • 4,802
  • 3
  • 25
  • 65
Mostafa Monowar
  • 881
  • 1
  • 8
  • 14

8 Answers8

74

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://stackoverflow.com/a/52985554/9909365

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

hata
  • 11,633
  • 6
  • 46
  • 69
Ashvin solanki
  • 4,802
  • 3
  • 25
  • 65
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()
        }
    }
}
Mostafa Monowar
  • 881
  • 1
  • 8
  • 14
  • [ref](https://developer.android.com/reference/android/view/PixelCopy#request(android.view.Window,%20android.graphics.Rect,%20android.graphics.Bitmap,%20android.view.PixelCopy.OnPixelCopyFinishedListener,%20android.os.Handler)) – olfek Feb 03 '19 at 16:00
  • 23
    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. – TheRealChx101 Feb 10 '19 at 13:03
  • 2
    @TheRealChx101 I found [this](https://stackoverflow.com/a/19383606/812919) today which I'm going to use instead. – olfek Feb 15 '19 at 23:30
  • 1
    `PixelCopy` requires API Level 26 and above. If you want compatability, for older API level, use the solution posted by @daka. – Morgan Koh Mar 12 '19 at 08:02
  • 1
    @daka you can use [link](https://github.com/Muddz/PixelShot) this library. It handles all stuffs for saving an image of a view. – Mostafa Monowar Mar 12 '19 at 10:56
  • A better and optimised solution would be "view.drawToBitmap()" – Othmane_lam Feb 05 '23 at 17:19
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
}
Shyam Kumar
  • 909
  • 11
  • 12
2

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

scienticious
  • 438
  • 1
  • 7
  • 22
Antonio Vlasic
  • 337
  • 3
  • 15
  • 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". – Mostafa Monowar Oct 04 '18 at 10:02
  • add an example of pixelCopy() to capture bitmap of view – Ashvin solanki Oct 20 '18 at 12:28
  • 1
    @Ashvinsolanki please checkout my answer. It works on. – Mostafa Monowar Oct 25 '18 at 09:11
  • how to use: https://medium.com/@hiteshkrsahu/a-complete-guide-for-taking-screenshot-in-android-28-bcb9a19a2b6e – Nick Kovalsky Sep 10 '20 at 06:58
  • The use of PixelCopy is not necessarily "should". The [docs](https://developer.android.com/reference/android/view/View.html#getDrawingCache()) only recommends using it for UI feedback report and unit tests. – mr5 Oct 10 '20 at 13:20
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
    }
Asad
  • 1,241
  • 3
  • 19
  • 32
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
}
Vlad
  • 7,997
  • 3
  • 56
  • 43
0
bitmap = view.drawToBitmap()
val pixel = bitmap.getpixel(x,y)
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
  • While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) 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. – Yunnosch May 25 '22 at 05:52
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

Shivanand Darur
  • 3,158
  • 1
  • 26
  • 32