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

Android中Canvas无法绘制矩形:onDraw方法参数恒为0 0 0 0

解决自定义View onDraw中矩形参数为0的问题

嘿,我看了你的日志和问题描述,这情况我之前也碰到过!核心问题其实是参数的保存和UI重绘触发的问题,咱们一步步拆解:

为什么构造函数能拿到正确值,但onDraw里是0?

从日志能看出来,构造函数的打印是在子线程(30639-31224),而onDraw的打印在主线程(30639-30639)。大概率是这两个原因:

  1. 你在构造函数里只是临时打印了参数,但没把参数赋值给自定义View的全局成员变量,onDraw的时候访问的是默认初始化的空Rect(全0值)。
  2. 就算你赋值了全局变量,但没有触发View的重绘,onDraw还是用的第一次绘制时的初始值;或者参数是在子线程更新的,主线程的onDraw看不到更新后的值(线程可见性问题)。

具体解决方案

1. 给自定义View加全局可访问的Rect变量

首先,在你的自定义View类里声明一个全局的Rect成员,并且初始化它:

public class YourCustomView extends View {
    private Paint mPaint;
    private volatile Rect mDrawRect; // 用volatile保证多线程下的可见性

    public YourCustomView(Context context) {
        super(context);
        init();
    }

    public YourCustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setColor(Color.RED);
        mDrawRect = new Rect(); // 初始化Rect,避免null
    }
}

2. 提供setter方法并触发重绘

给View加一个public的方法,用来从Activity接收矩形参数,关键是要调用invalidate()触发onDraw重绘:

public void updateDrawRect(Rect newRect) {
    if (newRect != null) {
        mDrawRect.set(newRect); // 复制新矩形的数值,避免外部修改直接影响View内部
    }
    invalidate(); // 必须调用这个,告诉系统View需要重绘了
}

3. 在Activity中正确传递参数

如果你的矩形参数是从子线程获取的(比如日志里的子线程打印),一定要切换到主线程调用setter方法:

// 假设这是你的Activity代码
YourCustomView customView = findViewById(R.id.your_custom_view);

// 如果参数来自子线程,用runOnUiThread切换到主线程
new Thread(() -> {
    // 模拟获取矩形参数的逻辑
    Rect targetRect = new Rect(153, 494, 535, 875);
    Log.v("drawrect", targetRect.left + " " + targetRect.top + " " + targetRect.right + " " + targetRect.bottom);
    
    // 切换到主线程更新View
    runOnUiThread(() -> {
        customView.updateDrawRect(targetRect);
    });
}).start();

4. 在onDraw中使用全局变量绘制

最后,在onDraw里直接用这个全局的mDrawRect就行:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Log.v("drawrectindraw", mDrawRect.left + " " + mDrawRect.top + " " + mDrawRect.right + " " + mDrawRect.bottom);
    canvas.drawRect(mDrawRect, mPaint);
}

这样改完之后,onDraw里就能拿到正确的矩形参数了,而且每次更新参数都会触发重绘,实现持续绘制的效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:13:08