Android开发中调用invalidate()无法刷新View问题求助
嘿,我之前重新捡Android开发的时候也踩过Canvas重绘的坑,给你几个实际排查的方向,应该能解决你的问题:
先确认invalidate()是不是在主线程调用
Android的UI更新必须在主线程执行,如果你的movePlayer方法是在子线程(比如触摸事件的处理、游戏逻辑线程)里调用的,直接调用invalidate()是不会生效的。这时候你需要把invalidate()放到主线程里执行,比如用runOnUiThread:// 在movePlayer修改完数组后,这样调用invalidate() runOnUiThread(() -> invalidate());检查你修改的数组是不是绘制时用的那一个
有时候会不小心创建了数组的副本,比如初始化的时候复制了一份,之后修改的是副本,但绘制时用的还是原数组。你可以在onDraw()方法里加个Log,打印一下数组中对应元素的y值,看看是不是已经更新到了你修改后的值。如果Log显示的还是旧值,那就是引用不对,要确保修改和绘制用的是同一个数组对象。验证onDraw()里的绘制逻辑是否依赖最新数据
比如你在onDraw()里绘制矩形的时候,是不是真的用了二维数组里的y值?有没有可能写死了固定的y坐标?举个正确的绘制示例:@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 遍历二维数组,用每个元素的y值来确定矩形位置 for (int row = 0; row < gameGrid.length; row++) { for (int col = 0; col < gameGrid[row].length; col++) { Rect rect = new Rect( col * CELL_WIDTH, gameGrid[row][col].y, // 这里必须是动态取数组里的y值 (col+1)*CELL_WIDTH, gameGrid[row][col].y + CELL_HEIGHT ); canvas.drawRect(rect, getPaintForCell(row, col)); } } }确认invalidate()的调用时机是否在数据修改之后
一定要先修改二维数组里的y值,再调用invalidate()。如果顺序搞反了,那触发重绘的时候数据还没更新,自然看不到变化。排查是否有View遮挡或Canvas裁剪问题
检查你的布局文件,看看CanvasActivity里的自定义View是不是被其他View(比如Toolbar、LinearLayout)挡住了?或者在onDraw()里有没有调用clipRect()之类的方法,限制了绘制区域,导致更新的部分不在可视范围内?
先从这几个方向查起,应该能找到问题所在!
内容的提问来源于stack exchange,提问作者cyrial

