Android Canvas中Bitmap无法适配屏幕问题求助
解决Canvas背景图片适配屏幕的问题
你的问题核心在于屏幕尺寸计算错误以及未采用正确的缩放绘制逻辑,以下是具体修正方案:
1. 修正尺寸计算逻辑
你当前写的fwidth = dm.density * dm.widthPixels是错误的:
dm.widthPixels本身就是屏幕的像素宽度,dm.density是dp转像素的转换系数,两者相乘会让计算出的尺寸远超实际屏幕大小,导致缩放后的图片超出显示范围,最终只呈现中间部分。- 正确做法是获取View自身的实际宽高(而非全局屏幕尺寸,因为你的View可能并非全屏显示),建议在
onSizeChanged方法中获取,避免初始化阶段拿到错误尺寸。
2. 正确的缩放适配实现
推荐使用canvas.drawBitmap(bitmap, srcRect, destRect, paint)的重载方法,直接将原图拉伸或缩放到View的整个显示区域:
修正后的完整代码
class DrawStars(context: Context) : View(context) { private var posX = 500f private var posY = 800f private val drawcolor: Int = ResourcesCompat.getColor(resources, R.color.black, null) private val paint = Paint().apply { color = drawcolor style = Paint.Style.STROKE isAntiAlias = true } private var background: Bitmap? = null private val srcRect = Rect() private val destRect = Rect() private var bitmap1: Bitmap? = null init { // 初始化图片资源 background = BitmapFactory.decodeResource(resources, R.drawable.fondo_sector2) bitmap1 = BitmapFactory.decodeResource(resources, R.drawable.star1) background?.let { srcRect.set(0, 0, it.width, it.height) } } override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { super.onSizeChanged(w, h, oldw, oldh) // 把目标区域设为View的完整范围 destRect.set(0, 0, w, h) } override fun onDraw(canvas: Canvas) { super.onDraw(canvas) background?.let { // 将原图缩放到View的整个区域绘制 canvas.drawBitmap(it, srcRect, destRect, paint) } bitmap1?.let { canvas.drawBitmap(it, posX, posY, paint) } } // 回收Bitmap避免内存泄漏 override fun onDetachedFromWindow() { super.onDetachedFromWindow() background?.recycle() bitmap1?.recycle() } }
关键修正点说明
- 用View实际宽高适配:通过
onSizeChanged获取View的w和h,确保适配View的真实显示区域,而非固定屏幕尺寸。 - Rect适配绘制:
srcRect对应原图的完整区域,destRect对应View的整个区域,drawBitmap会自动将原图拉伸/缩放到目标区域,实现全屏适配。 - 内存优化:添加
onDetachedFromWindow回收Bitmap,避免内存泄漏。 - 空安全处理:对Bitmap使用
let判空,防止空指针异常。
内容的提问来源于stack exchange,提问作者Delek
相关产品推荐
相关产品推荐

