IllegalArgumentException: 从视图加载位图时宽度和高度必须大于0。

34

我正在尝试在ImageViewTouch上进行绘制,这是一个可以缩放的库。我能够使用Canvas在图像上绘制,但是当我缩放图像时,绘图会消失。

为了解决这个问题,我正在尝试将视图转换为位图,并为相同的视图设置ImageBitmap。以下是代码:

mImage.setDrawPath(true);
mImage.setImageBitmap(loadBitmapFromView(mImage)); 

public static Bitmap loadBitmapFromView(View v) {
        Bitmap b = Bitmap.createBitmap( v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);                
        Canvas c = new Canvas(b);
        v.layout(0, 0, v.getWidth(), v.getHeight());
        v.draw(c);
        return b;
}

我这样做时,会得到以下日志错误:

07-11 21:13:41.567: E/AndroidRuntime(20056): java.lang.IllegalArgumentException: width and height must be > 0
07-11 21:13:41.567: E/AndroidRuntime(20056):    at android.graphics.Bitmap.createBitmap(Bitmap.java:638)
07-11 21:13:41.567: E/AndroidRuntime(20056):    at android.graphics.Bitmap.createBitmap(Bitmap.java:620)

如果我删除loadBitmapFromView 调用,绘画通常会出现在图像上。但是当我尝试对图像进行任何交互(比如缩放)时,绘画就消失了,只剩下背景图像。

--- 编辑 ---

以下是在loadBitmapFromView调用之后添加的一些代码。情况是:我有一个单选按钮组侦听器,当我选中某个单选按钮时,我必须加载图片并在其上绘制一些可能的图画...然后我试图将所有东西(图片和图画)转换为一个位图。

以下是代码的其他部分:

bitmap = BitmapUtils.decodeSampledBitmapFromResource(root + DefinesAndroid.CAMINHO_SHOPPINGS_SDCARD + nomeImagemAtual, size.x, size.y);
mImage.setImageBitmap(bitmap);

之后,我画出所有需要画的东西,并尝试使用我展示过的loadImageBitmap方法将视图转换为位图。

我从android开发者官网这个链接中获得了decodeSampledBitmapFromResource方法:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

6个回答

49

我终于找到了解决方案。

我正在使用View的post方法,它会在视图测量和布局之后执行,这样getWidth()getHeight()将返回实际的宽度和高度。

下面是代码示例:

mImage.post(new Runnable() {
    @Override
    public void run() {
        mImage.setImageBitmap(loadBitmapFromView(mImage));
    }
});

希望这也能帮助到其他人 :)


2
你好,能否再解释一下?所以无论在哪里设置图像位图,只需像上面那样将其放入“Runnable”中,那么宽度和高度就不再是问题了吗? - Azurespot
1
代码适用于所有的Android API,而不是API 21(棒棒糖)。我正在使用三星S4设备,但这些代码也没有帮助到我。 - Ready Android

10
如果其他内容都正确,那么您正在过早地执行代码。
Android尚未测量视图的布局。尝试在OnResume中执行,看看是否是您的问题。
干杯!

我可能正在做你所说的事情,因为在调用这个setImageBitmap之前,我调用了另一个。我已经编辑了问题并加入了更多的解释! - Felipe Mosso
我不明白你说的在OnResume中尝试执行的时候是什么意思。我在单选按钮更改侦听器上设置了位图,但活动仍然是相同的:( 你能否通过展示一些代码来说明它?谢谢! - Felipe Mosso

8
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            loadBitmapFromView(mImage);
        }
    }, 1000);

1

java.lang.IllegalArgumentException: 宽度和高度必须大于0是因为在你的Bitmap.createBitmap()调用中,v.getLayoutParams().widthv.getLayoutParams().height为0。可能是mImageLayoutParams设置错误。

更新:在使用createBitmap()之前为mImage设置setLayoutParams()。类似以下代码:

LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(30, 30);
mImage.setLayoutParams(layoutParams);

是的,我已经检查过了,它们确实是零。但为什么呢?我只是将之前的视图作为参数传递,但现在这个视图上已经绘制了画布。 - Felipe Mosso
@FelipeMosso 你是在视图呈现给用户之前还是之后传递它?如果我没记错,如果在之前传递它,那么 getLayoutParams().heightgetLayoutParams().width 的值将为0。 - nick
我在用户看到内容之前就传递了数据,因为我需要先将所有图形都绘制出来呈现给用户。我已经编辑了问题并添加了更多信息,请您查看一下,谢谢 :) - Felipe Mosso
我该怎么样在向用户展示后传递它呢?我真的卡住了 :( - Felipe Mosso
请查看我的更新。如果没有帮助,请发布所有涉及“mImage”的代码。 - Adam Stelmaszczyk

1
在我的情况下,我忘记为父级LinearLayout设置orientationvertical,导致默认值horizontal被设置,所以我将其设置为vertical,问题就解决了...
android:orientation="vertical"

0
我不确定是否与此特定问题相关,但我遇到了同样的错误,并通过从 drawable 而不是 mipmap 获取图像源来解决它(当然,我必须先将图像放在那里)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接