【问题标题】:Draw background of custom View from .png file on Android在 Android 上从 .png 文件绘制自定义视图的背景
【发布时间】:2012-01-26 08:24:56
【问题描述】:

我通过从 View 扩展创建了一个自定义 View。在 onDraw() 我设法画了一些圆圈和其他东西。但现在我想从资源(sd 卡或流)中添加背景,这实际上是我从服务器下载的地图,然后在上面绘制。适用于 Android 8+

@Override
protected void onDraw(Canvas canvas) {
    Canvas g = canvas;
    String file = "/mnt/sdcard/download/tux.png";
    Bitmap bg = null;
    try {
        bg = BitmapFactory.decodeFile(file);
        g.setBitmap(bg);
    } catch (Exception e) {
        Log.d("MyGraphics", "setBitmap() failed according to debug");
    }
}

不知何故 g.setBitmap(bg) 一直失败,我没有查看图像规格,但实际上它只是 PNG 格式的 tux 图像(没有 24 位颜色)。 有人可以给我一些提示如何添加背景图像以便我可以在上面画画吗? 谢谢。

【问题讨论】:

    标签: android view background paint android-canvas


    【解决方案1】:

    您实际上不想在您加载的位图上绘制,您只想在 Canvas 上绘制它,因此您应该使用 Canvas.drawBitmap()。您也不应该在每个 onDraw() 中加载位图,而是在构造函数中加载。试试这个课程:

    package com.example.android;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.util.AttributeSet;
    import android.view.View;
    
    public class CustomView extends View {
        private final Bitmap mBitmapFromSdcard;
    
        public CustomView(Context context) {
            this(context, null);
        }
    
        public CustomView(Context context, AttributeSet attrs) {
            super(context, attrs);
            mBitmapFromSdcard = BitmapFactory.decodeFile("/mnt/sdcard/download/tux.png");
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            Canvas g = canvas;
            if (mBitmapFromSdcard != null) {
                g.drawBitmap(mBitmapFromSdcard, 0, 0, null);
            }
        }
    }
    

    你也可以让Android在后台绘制位图:

    package com.example.android;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.drawable.BitmapDrawable;
    import android.util.AttributeSet;
    import android.view.View;
    
    public class CustomView extends View {
        public CustomView(Context context) {
            this(context, null);
        }
    
        public CustomView(Context context, AttributeSet attrs) {
            super(context, attrs);
            Bitmap bm = BitmapFactory.decodeFile("/mnt/sdcard/download/tux.png");
            if (bm != null) {
                setBackgroundDrawable(new BitmapDrawable(bm));
            }
        }
    }
    

    【讨论】:

    • Martin,非常感谢您提供这个清晰的示例。奇怪的是我已经做了你的第一个例子,但不知何故它不起作用!那就是我开始迷路的地方。第二个是拉伸以适应视图的房地产,这正是最终的结果。但是你的第一个我更喜欢它,这样我可以在不修改大小的情况下定位图片。
    • 当您尝试我的第一个示例时,究竟什么不起作用?一个例外(如果是,什么例外)?屏幕上什么都没有绘制?你在哪个安卓版本上运行?您能否提供您使用的确切代码,您希望它可以工作,但事实并非如此?
    • 我的朋友,.png 和 .jpg 都可以。在你的帖子之后,我还在玩并尝试了一些图片,发现并非所有的 .jpeg 文件都有效。当我使用像 50 KB 这样的小 jpg 图片时,它可以工作,但是当使用像 600 KB 这样的较大 jpg 图片时,背景会变成完全白色。我不知道这是否与图像尺寸有关,因为那些不起作用的尺寸比我视图的房地产大得多。使用 setBackgroundDrawable() 确实有效,但它也会缩小到 View 的实际大小。
    【解决方案2】:

    我担心你会得到 OutOfMemoryError,因为 onDraw 在视图生命周期中被多次调用,并且每次你都在为新的位图分配内存。只需创建类的 bg 成员(可能是静态的)并仅加载一次 - 在视图的构造函数中。并且不要忘记在视图分离时回收位图。

    【讨论】:

    • 嗯,第一次出现这种情况,我在上面放了一个断点:bg = BitmapFactory.decode(file);调试时,g.setBitmap(bg)出现异常;我收到 IllegalStateException,但无法检索有关此异常的更多信息。恐怕与位图的大小或密度有关,但我对图形的了解有限。
    • 好的,我发现 bg = BitmapFactory.decodeFile(file);返回一个不可变的位图,这意味着我不能在上面绘图。有人可以提供一个简单的示例,如何从文件(或字节数组)加载图像并将其作为自定义视图的背景图像,以便我可以在视图的 onDraw() 处理程序中绘制它吗?只是一个简单的例子,谢谢。
    • 我可以提出两种方法来制作这样的东西:1)内部调用 View.setBackgroundDrawable() (以前你需要从位图创建 BitmapDrawable); 2) 调用 g.drawBitmap() 而不是 g.setBitmap()。在这种情况下,您不是替换画布源,而是在其中绘制。
    • 是的,谢谢,BitmapDrawable 为我解决了问题。我现在必须找出如何在不缩放等情况下显示它。但这是另一个故事,谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-12
    相关资源
    最近更新 更多