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

Android自定义View的onDraw方法无法更新Canvas内Bitmap位置如何解决

问题根因

你遇到的核心错误有两个:

  1. 你注释了触发View重绘的invalidate()方法,反而主动调用了customView.draw(canvas)方法。Android View的绘制流程由系统统一调度,你手动传入的canvas并非系统最终用来渲染到屏幕的目标画布,所以你用新x值绘制的内容不会显示到用户可见的界面上,这也是为什么你Log里能看到x值更新,但界面上Bitmap位置没变的原因。
  2. 你没有主动通知系统你的View内容发生了变化,系统不会主动重新调用onDraw方法刷新界面,用户看到的永远是第一次系统调度绘制时的结果。
修复方案
  • 删掉Activity中所有customView.draw(canvas)的调用,打开invalidate()的注释,修改完x值后直接调用invalidate()通知系统重绘即可。
  • 优化自定义View的代码,避免在onDraw中重复创建Paint对象,调整super.onDraw的调用顺序到方法开头(避免自定义绘制内容被父类逻辑覆盖)。

修复后的Activity代码

if (callback2 > 0 && callback2 <= 0.1) {
    customView.x = 468;
    customView.invalidate();
} else if (callback2 < 0) {
    customView.x = 650;
    customView.invalidate();
} else if (callback2 > 0.1) {
    customView.x = 270;
    customView.invalidate();
}

注意:如果你的上述代码是在非UI线程中执行,需要把invalidate()替换为postInvalidate(),避免线程报错。

修复后的自定义View代码

public class TheCustomView extends View {
    Bitmap scaledRollerBottom;
    Bitmap backgroundMask;
    Bitmap rollerBottom;
    Bitmap overlayBitmap;
    float x;
    // 全局共用Paint,避免onDraw中重复创建造成内存抖动
    private Paint mPaint;


    public TheCustomView(Context context) {
        super(context);
        initPaint();
    }
    
    public TheCustomView(Context context, AttributeSet attr) {
        super(context, attr);
        initPaint();
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        backgroundMask = BitmapFactory.decodeResource(getResources(), R.drawable.background_new, options);
        rollerBottom = BitmapFactory.decodeResource(getResources(), R.drawable.roller_bottom, options);

        Bitmap scaledBackgroundMask = Bitmap.createScaledBitmap(backgroundMask, 1000, 1000, true);
        scaledRollerBottom = Bitmap.createScaledBitmap(rollerBottom, 120, 31, false);
    }

    private void initPaint() {
        mPaint = new Paint();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // 先调用父类绘制逻辑,再执行自定义绘制
        super.onDraw(canvas);
        Log.v("X  ", "is " + x);
        canvas.drawBitmap(scaledRollerBottom, x, 915f, mPaint);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 20:54:04