You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android开发中Canvas如何处理屏幕方向旋转适配问题

Android Canvas 屏幕旋转内容移出可视区域修复方案

问题核心原因

  • 初始化的缓存Bitmap为正方形,边长取屏幕长宽最大值,屏幕旋转后自定义View的可视区域尺寸发生变化,始终从(0,0)坐标绘制Bitmap会导致Bitmap超出View边界的部分被直接裁切。
  • 未正确处理屏幕旋转的配置变更,默认旋转时Activity会重建,若没有做内容转储,已绘制内容会直接丢失。
  • 初始化Bitmap的时机在View构造函数中,此时View未完成测量,拿到的屏幕尺寸和实际View绘制区域尺寸可能存在偏差。

具体修复步骤

  • 调整绘制逻辑,增加居中偏移计算
    修改onDraw方法,绘制Bitmap和临时路径时增加居中偏移,保证画布内容始终对齐当前View的中心:
override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    canvas.apply {
        drawColor(0)
        // 计算偏移量,让Bitmap中心和当前View中心重合
        val offsetX = (width - mBitmap.width) / 2f
        val offsetY = (height - mBitmap.height) / 2f
        drawBitmap(mBitmap, offsetX, offsetY, mBitmapPaint)
        // 正在绘制的临时路径也要加相同偏移,保证绘制位置和缓存内容对齐
        drawPath(mPath, offsetX, offsetY, mPaint)
    }
}
  • 拦截配置变更,避免旋转时重建清空内容
    在AndroidManifest.xml中对应承载画布的Activity节点添加配置拦截属性:
<activity
    android:name=".YourCanvasActivity"
    android:configChanges="orientation|screenSize|keyboardHidden"
    android:exported="false">
</activity>
  • 把Bitmap初始化和扩容逻辑移到onSizeChanged回调中
    不要在View的init块中直接创建Bitmap,onSizeChanged会在View首次测量完成、旋转导致尺寸变化时触发,在这里做初始化和扩容,同时保留旧Bitmap的绘制内容:
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
    super.onSizeChanged(w, h, oldw, oldh)
    // 首次初始化
    if (!::mBitmap.isInitialized) {
        val initSize = max(w, h)
        createBitmap(initSize, initSize)
        return
    }
    // 尺寸超过现有Bitmap大小时再扩容,避免内容丢失
    if (w > mBitmap.width || h > mBitmap.height) {
        val newW = max(w, mBitmap.width)
        val newH = max(h, mBitmap.height)
        val newBitmap = Bitmap.createBitmap(newW, newH, Bitmap.Config.ARGB_8888)
        val tempCanvas = Canvas(newBitmap)
        // 将旧内容绘制到新Bitmap上
        tempCanvas.drawBitmap(mBitmap, 0f, 0f, null)
        // 回收旧Bitmap,替换引用
        mBitmap.recycle()
        mBitmap = newBitmap
        mCanvas.setBitmap(newBitmap)
    }
}

把原来init块中调用createBitmap()的代码删掉即可。

注意点

  • 所有通过mCanvas绘制到缓存Bitmap的坐标,不需要加偏移量,偏移只在onDraw把缓存绘制到屏幕Canvas时处理,避免出现坐标偏移叠加的问题。
  • 如果需要支持分屏、自由窗口等可变尺寸场景,这套逻辑也能自动适配,不需要额外修改。

内容的提问来源于stack exchange,提问作者oyeraghib

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 12:12:21