Android中Canvas无法绘制矩形:onDraw方法参数恒为0 0 0 0
解决自定义View onDraw中矩形参数为0的问题
嘿,我看了你的日志和问题描述,这情况我之前也碰到过!核心问题其实是参数的保存和UI重绘触发的问题,咱们一步步拆解:
为什么构造函数能拿到正确值,但onDraw里是0?
从日志能看出来,构造函数的打印是在子线程(30639-31224),而onDraw的打印在主线程(30639-30639)。大概率是这两个原因:
- 你在构造函数里只是临时打印了参数,但没把参数赋值给自定义View的全局成员变量,onDraw的时候访问的是默认初始化的空Rect(全0值)。
- 就算你赋值了全局变量,但没有触发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
相关产品推荐
相关产品推荐

