将 ListView 转换为位图

Converting a ListView to Bitmap

提问人:flowerProgrammer 提问时间:10/25/2023 最后编辑:flowerProgrammer 更新时间:10/25/2023 访问量:42

问:

我想将 ListView 转换为位图图像。 以下代码工作正常,但列表长于屏幕的情况除外。我设法使画布达到所需的大小,但它仍然只显示适合屏幕的元素,而另一个区域只是白色:

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
}

我怎样才能修复它以包含整个列表?

Android Kotlin ListView 位图

评论

0赞 Ticherhaz FreePalestine 10/25/2023
您是否尝试过更改为Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
0赞 flowerProgrammer 10/25/2023
@TicherhazFreePalestine是的,它只是制作一个仅包含可见内容的屏幕截图,而不是整个列表
1赞 Ticherhaz FreePalestine 10/25/2023
stackoverflow.com/questions/30085063/......可以在这里检查是否有帮助
0赞 flowerProgrammer 10/25/2023
谢谢@TicherhazFreePalestineThe!我根据我的情况调整了它。
0赞 Ticherhaz FreePalestine 10/25/2023
好。对你好。不客气。:D

答:

-1赞 flowerProgrammer 10/25/2023 #1

我设法通过调整 Kotlin 中 ListView 的 RecyclerView 全长屏幕截图中的代码来使其工作。感谢您的帮助。

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
}
0赞 Marcin Mrugas 10/25/2023 #2
 fun getBitmapFromView(listView: ListView): Bitmap {
        val listAdapter = listView.adapter
        var totalHeight = listView.paddingTop + listView.paddingBottom
        val desiredWidth = listView.width
        for (i in 0 until listAdapter.count) {
            val childView = listAdapter.getView(i, null, listView)
            val widthMeasureSpec = MeasureSpec.makeMeasureSpec(desiredWidth, MeasureSpec.EXACTLY);
            childView.measure(widthMeasureSpec, MeasureSpec.UNSPECIFIED)
            childView.layout(0, 0, childView.measuredWidth, childView.measuredHeight)
            totalHeight += childView.measuredHeight
        }

        val bitmap = Bitmap.createBitmap(listView.width, totalHeight, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bitmap)
        var topDrawDistance = 0
        for (i in 0 until listAdapter.count) {
            val childView = listAdapter.getView(i, null, listView)
            val widthMeasureSpec = MeasureSpec.makeMeasureSpec(desiredWidth, MeasureSpec.EXACTLY);
            childView.measure(widthMeasureSpec, MeasureSpec.UNSPECIFIED)
            val childBitmap = Bitmap.createBitmap(childView.measuredWidth, childView.measuredHeight, Bitmap.Config.ARGB_8888)
            val childCanvas = Canvas(childBitmap)
            childView.layout(0, 0, childView.measuredWidth, childView.measuredHeight)
            childView.draw(childCanvas)
            canvas.drawBitmap(
                childBitmap,
                Rect(0, 0, childView.measuredWidth, childView.measuredHeight),
                Rect(0, topDrawDistance, childView.measuredWidth, topDrawDistance + childView.measuredHeight),
                Paint()
            )
            topDrawDistance += childView.measuredHeight
        }
        return bitmap
    }

注意事项:

  1. 不再推荐使用 ListView,RecyclerView 是用于创建列表的较新版本。
  2. 如果要绘制整个列表,则必须单独绘制每个项目,因为屏幕下方的项目尚未呈现。
  3. 你需要调用函数layout()
  4. 父视图的绘图背景是无用的,因为它的高度等于屏幕高度。
  5. 在适配器中迭代项目时,请使用循环变量而不是静态变量i0