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

Android Studio:MainActivity修改其他类变量不影响Canvas绘图

问题原因

你在MainActivity和自定义Canvas View中分别声明了val p = Properties(),这意味着你创建了两个完全独立的Properties实例:

  • 自定义View内部使用的是自己作用域内的p对象
  • MainActivity修改的是自身作用域内的另一个p对象
    两者毫无关联,所以即便你调用invalidate()触发重绘,Canvas依然会使用自己持有的p.x值,自然看不到界面变化。
解决方法

以下是几种可行的解决方案,可根据场景选择:

方案1:让View与Activity共享同一个实例

修改自定义Canvas类,通过构造函数或公开属性传入共享的Properties对象:

// 自定义View不再单独创建p实例
class CanvasView(context: Context?, attrs: AttributeSet) : View(context, attrs) {
    lateinit var p: Properties // 声明外部传入的属性
    private val myPaint = Paint().apply { color = Color.RED }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        canvas.drawCircle(p.x, 100f, 10f, myPaint)
    }
}

在MainActivity中创建实例并传递给View:

lateinit var canvasView: CanvasView
val p = Properties()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    enableEdgeToEdge()
    setContentView(R.layout.activity_main)

    canvasView = findViewById(R.id.canvasView)
    canvasView.p = p // 传递同一个实例

    p.x = 700f
    canvasView.invalidate()
}

方案2:将Properties设计为单例

如果这个属性是全局唯一的,可以把Properties改成单例模式,确保所有地方访问的是同一个实例:

class Properties private constructor() {
    var x = 200f
    companion object {
        val instance: Properties by lazy { Properties() }
    }
}

在自定义View和MainActivity中统一使用单例:

// 自定义View中
val p = Properties.instance

// MainActivity中
val p = Properties.instance

修改p.x后调用invalidate()即可触发界面更新。

方案3:在View中提供修改属性的方法

在自定义View中封装属性修改逻辑,直接对外暴露修改方法:

class CanvasView(context: Context?, attrs: AttributeSet) : View(context, attrs) {
    private val p = Properties()
    private val myPaint = Paint().apply { color = Color.RED }

    fun updateCircleX(newX: Float) {
        p.x = newX
        invalidate() // 内部直接触发重绘,无需外部调用
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        canvas.drawCircle(p.x, 100f, 10f, myPaint)
    }
}

在MainActivity中直接调用View的方法:

lateinit var canvasView: CanvasView

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    enableEdgeToEdge()
    setContentView(R.layout.activity_main)

    canvasView = findViewById(R.id.canvasView)
    canvasView.updateCircleX(700f)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 04:57:03