Search code examples
androidkotlinlistviewbitmap

Converting a ListView to Bitmap


I want to convert a ListView to a bitmap image. The following code works fine, except in cases where the list is longer then the screen. I managed to get the canvas to the desired size, but it still shows only the elements that fit in the screen and the other area is just white:

fun getBitmapFromView(view: ListView): Bitmap {
    val listAdapter = view.adapter
    var totalHeight = listView.paddingTop + listView.paddingBottom
    val desiredWidth = MeasureSpec.makeMeasureSpec(listView.width, MeasureSpec.AT_MOST)
    for (i in 0 until listAdapter.getCount()) {
        val listItem: View = listAdapter.getView(i, null, listView)
        if (listItem != null) {
            listItem.layoutParams =
                RelativeLayout.LayoutParams(
                    RelativeLayout.LayoutParams.WRAP_CONTENT,
                    RelativeLayout.LayoutParams.WRAP_CONTENT
                )
            listItem.measure(desiredWidth, MeasureSpec.UNSPECIFIED)
            totalHeight += listItem.measuredHeight
        }
    }

    val bitmap  = Bitmap.createBitmap(view.width, totalHeight, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(bitmap )
    val bgDrawable = view.background
    if (bgDrawable != null) bgDrawable.draw(canvas) else canvas.drawColor(Color.WHITE)
    view.draw(canvas)
    return bitmap
}

How can I fix it to contain the whole list?


Solution

  • I managed to get it to work by adjusting the code in Take a screenshot of RecyclerView in FULL length for ListView in Kotlin. Thanks for your help.

    fun getBitmapFromView(listView: ListView): Bitmap? {
        val adapter: ListAdapter = listView.adapter
        var bigBitmap: Bitmap? = null
        if (adapter != null) {
            val size = adapter.count
            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 itemView = adapter.getView(i, null, listView) as View
                itemView.measure(
                    View.MeasureSpec.makeMeasureSpec(listView.width, View.MeasureSpec.EXACTLY),
                    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
                )
                itemView.layout(0, 0, itemView.measuredWidth, itemView.measuredHeight)
                itemView.isDrawingCacheEnabled = true
                itemView.buildDrawingCache()
                val drawingCache = itemView.drawingCache
    
                if (drawingCache != null) {
                    bitmapCache.put(i.toString(), drawingCache)
                }
                height += itemView.measuredHeight
            }
    
            bigBitmap = Bitmap.createBitmap(listView.width, height, Bitmap.Config.ARGB_8888)
            val bigCanvas = Canvas(bigBitmap)
            bigCanvas.drawColor(Color.WHITE)
    
            for (i in 0 until size) {
                val bitmap = bitmapCache.get(i.toString())
                bigCanvas.drawBitmap(bitmap, 0f, iHeight.toFloat(), paint)
                iHeight += bitmap?.height ?: 0
                bitmap?.recycle()
            }
        }
        return bigBitmap
    }