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

onCreate中加载图片至自定义Canvas视图无效的问题与解决

问题:Activity启动时无法将Bitmap加载到自定义Canvas View,点击按钮却正常显示

我自定义了一个包含Canvas的View,在Activity的onCreate方法中从内部存储加载Bitmap并设置到该Canvas,但图片无法显示;不过在OnClickListener中执行相同的设置Bitmap操作时,图片却能正常显示。请问问题出在哪里?如何在Activity启动时自动将图片加载到Canvas?

我的代码如下:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_sign);
    signatureView = findViewById(R.id.signView);
    clearBtn = findViewById(R.id.clearBtn);
    acceptSignBtn = findViewById(R.id.acceptSignBtn);
    String fileName = getIntent().getStringExtra("photo");
    try {
        FileInputStream fis = openFileInput(fileName);
        byte[] byteArray = new byte[getIntent().getIntExtra("size", fis.available())];
        fis.read(byteArray);
        fis.close();
        photo = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
        photo = photo.copy(Bitmap.Config.ARGB_8888, true);
        Log.i("TAG", "load done" +photo.getHeight());
        signatureView.setBitmap(photo); //There is no result, canvas stay clear
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    clearBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            signatureView.clearCanvas();
            signatureView.setBitmap(photo); //after click photo appears
        }
    });
}

问题出在哪?

核心原因是View的绘制时序问题:
在Activity的onCreate方法执行阶段,你的自定义signatureView还没完成「测量(measure)」和「布局(layout)」流程——此时View的宽高还没确定,甚至View的第一次onDraw可能已经跑完了。你这时候调用setBitmap,虽然Bitmap已经传给了View,但没有触发View的重新绘制,所以图片自然不会显示。

而点击按钮的时候,View早就完成了所有初始化和绘制流程,这时候调用setBitmap,要么是按钮点击事件间接触发了View的重绘,要么是你的clearCanvas方法里已经调用了invalidate()(触发重绘),所以图片能正常显示出来。

怎么解决?

这里有几个简单可靠的方案,任选其一即可:

方案1:用View的post方法延迟执行

post会把任务放到View的消息队列里,等View彻底完成布局和初始化后再执行,这样就能保证View已经准备好接收Bitmap并绘制:

// 把onCreate里的signatureView.setBitmap(photo);替换成下面这段
signatureView.post(new Runnable() {
    @Override
    public void run() {
        signatureView.setBitmap(photo);
    }
});

方案2:在自定义View的setBitmap里主动触发重绘

检查一下你的SignatureView类里的setBitmap方法,如果没有调用invalidate(),一定要加上——这个方法会告诉系统:「这个View内容变了,赶紧重新画一遍!」

// 自定义SignatureView中的setBitmap方法示例
public void setBitmap(Bitmap bitmap) {
    this.mBitmap = bitmap;
    // 关键:触发View重绘
    invalidate();
}

这样哪怕你在onCreate里调用setBitmap,后续View完成布局后,invalidate()会触发onDraw,图片就能正常显示了。

方案3:在Activity的onWindowFocusChanged中加载

当Activity获取到窗口焦点时,所有View都已经完成布局了,这时候再设置Bitmap肯定没问题:

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    // 确保只有第一次获取焦点且photo不为空时执行
    if (hasFocus && photo != null) {
        signatureView.setBitmap(photo);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:23:27