Android 如何覆盖 onDraw 以便我将绘制的内容(作为位图)转换为它?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2763572/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 07:16:24  来源:igfitidea点击:

How can I override onDraw so that I take what would have been drawn (as a bitmap) and transform it?

android

提问by Casebash

The method below works, but it unfortunately, this method involves creating a bitmap the size of the entire screen - not just the area that is drawn to. If I use this to draw UI elements, it is redrawn for each UI element. Can this be done more efficiently?

下面的方法有效,但不幸的是,该方法涉及创建一个与整个屏幕大小相同的位图 - 而不仅仅是绘制到的区域。如果我用它来绘制 UI 元素,它会为每个 UI 元素重新绘制。这可以更有效地完成吗?

@Override
protected void onDraw(Canvas canvas) {
    //TODO: Reduce the burden from multiple drawing
    Bitmap bitmap=Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Config.ARGB_8888);
    Canvas offscreen=new Canvas(bitmap);
    super.onDraw(offscreen);
    //Then draw onscreen
    Paint p=new Paint();
    p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN));
    canvas.drawBitmap(bitmap, 0, 0, p);
}

回答by Casebash

The following code will be much more efficient.

下面的代码会更有效率。

public class MyView extends TextView{
    private Canvas offscreen;

    public MyView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyView(Context context) {
        super(context);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //We want the superclass to draw directly to the offscreen canvas so that we don't get an infinitely deep recursive call
        if(canvas==offscreen){
            super.onDraw(offscreen);
        }
        else{
            //Our offscreen image uses the dimensions of the view rather than the canvas
            Bitmap bitmap=Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888);
            offscreen=new Canvas(bitmap);
            super.draw(offscreen);
            //Create paint to draw effect
            Paint p=new Paint();
            p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN));
            //Draw on the canvas. Fortunately, this class uses relative coordinates so that we don't have to worry about where this View is actually positioned.
            canvas.drawBitmap(bitmap, 0, 0, p);
        }
    }
}

回答by Steve Haley

Have you tried changing the size of the bitmap you create, to be only equal to the clip bounds rather than the entire size of the given canvas? I don't know if this is the case with all Views, but I found that the onDraw method for some Views is given a canvas as big as the screen, regardless of the actual size of the content. It then clips the canvas, restricting it to the top left corner only, draws there and then translates that part to somewhere else on the screen when it's actually ready to display the whole layout. In other words, despite it having a canvas the size of the whole screen, it only actually uses a small piece of it. So what you could try doing is instead of using

您是否尝试过更改您创建的位图的大小,使其仅等于剪辑边界而不是给定画布的整个大小?我不知道所有的 View 是否都是这种情况,但我发现某些 View 的 onDraw 方法被赋予了一个与屏幕一样大的画布,而不管内容的实际大小。然后剪辑画布,将其限制在左上角,在那里绘制,然后在实际准备好显示整个布局时将该部分转换到屏幕上的其他位置。换句话说,尽管它有一个整个屏幕大小的画布,但它实际上只使用了其中的一小部分。所以你可以尝试做的是而不是使用

Bitmap bitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), ...)

you could try

你可以试试

Rect rect = canvas.getClipBounds();
int width = rect.width();
int height = rect.height();
Bitmap bitmap = Bitmap.createBitmap(width, height, ...); 

That way you reduce the overhead of working with a much larger bitmap than necessary. Note: I haven't actually tried doing this so it might not work, but it's worth trying.

这样您就可以减少使用比必要的大得多的位图的开销。注意:我还没有真正尝试过这样做,所以它可能不起作用,但值得一试。

回答by Bruce

I encountered something similar, where canvas.getWidth() and canvas.getHeight() returns the width and height of the whole screen instead of the view itself.

我遇到了类似的事情,其中​​ canvas.getWidth() 和 canvas.getHeight() 返回整个屏幕的宽度和高度,而不是视图本身。

Try to use the below instead:

尝试使用以下内容:

Bitmap bitmap=Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888);

For my case, getWidth() and getHeight() returns me the dimensions of my view. Good luck!

对于我的情况, getWidth() 和 getHeight() 返回我视图的尺寸。祝你好运!