Android的自定义视图不处理透明度/阿尔法的正确方法 [英] Android Custom View doesn't handle transparency/alpha the right way

查看:194
本文介绍了Android的自定义视图不处理透明度/阿尔法的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我画一个自定义视图。在这个观点我使用两种不同的油漆和路径的对象画在画布上。我基本上绘图重叠的两个形状。之后予添加α,即重叠视图的部分比图像的其余部分更暗。这是不需要的,但我不知道如何解决它。

I'm drawing a custom view. In this view I use two different paint and path objects to paint to the canvas. I'm basically drawing two shapes that overlap. After I add alpha, the part of the view that is overlapped is darker than the rest of the image. This is undesired, but I'm not sure how to fix it.

这是我的code进行裁剪,以显示我如何使用阿尔法在我NewButtonView.java

This is a clipping of my code to show how I'm using alpha in my NewButtonView.java

Paint paint = new Paint();
int color = 0x33ffffff;
int borderColor = 0xFF000000;

paint.setColor(color);
paint.setAntiAlias(true);
paint.setStrokeWidth(strokeWidth);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStyle(Paint.Style.FILL);

约31分钟进入这种谷歌I / O影片 .. 。他们表现出我想要的效果。

About 31 minutes into this Google I/O video... they show my desired effect.

他们基本上显示此图像:

They basically show this image:

添加透明和得到这个形象:令人失望的结果。

Add transparency and get this image: UNDESIRED RESULT

他们结束了这一点:想要的结果。

They end up with this: DESIRED RESULT

有没有人对如何得到这个期望的影响?任何想法

Does anyone have any idea on how to get this desired affect?

推荐答案

正如视频中,你可以使用画布#saveLayerAlpha(....)此。您也可以得到类似的效果,而无需使用它。我将讨论以后。

As mentioned in the video, you would use Canvas#saveLayerAlpha(....) for this. You can also get a similar effect without using it. I'll discuss that later on.

让我们创建一个示例视图:

Let's create a sample view:

public class SampleView extends View {

    // Declare Paint objects
    Paint paintColor, paintBorder;

    public SampleView(Context context) {
        super(context);

        // Initialize and set up Paint objects
        paintColor = new Paint();
        paintBorder = new Paint();

        paintColor.setAntiAlias(true);
        paintBorder.setAntiAlias(true);

        paintBorder.setColor(Color.BLACK);
        paintBorder.setStyle(Style.STROKE);
        paintBorder.setStrokeWidth(10);

        // Just a random image to 'see' the difference
        setBackground(getResources().getDrawable(R.drawable.hor_lines));
    }

    @Override 
    protected void onDraw(Canvas canvas) {

        // Save layer alpha for Rect that covers the view : alpha is 90 / 255
        canvas.saveLayerAlpha(0, 0, getWidth(), getHeight(), 90, 
                                             Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);

        // Draw first circle, and then the border
        paintColor.setColor(Color.RED);
        canvas.drawCircle(getWidth() / 3, getHeight() / 2, 
                                           getWidth() / 4 - 20, paintColor);

        canvas.drawCircle(getWidth() / 3, getHeight() / 2, 
                                           getWidth() / 4 - 15, paintBorder);

        // Draw second circle, and then the border
        paintColor.setColor(Color.BLUE);
        canvas.drawCircle(2 * getWidth() / 3, getHeight() / 2, 
                                           getWidth() / 4 - 20, paintColor);
        canvas.drawCircle(2 * getWidth() / 3, getHeight() / 2, 
                                           getWidth() / 4 - 15, paintBorder);

        // Finally, restore the canvas
        canvas.restore();
    }
}

会发生什么:

What happens:

  1. saveLayerAlpha(....)被称为离屏位图被分配。

  1. An off-screen bitmap is allocated when saveLayerAlpha(....) is called.

所有的绘制操作都发生在此位图。

All drawing operations happen on this bitmap.

canvas.restore()被调用时,该位被转移到屏幕上的帆布,以及我们提供的Alpha值 saveLayerAlpha(....)被施加到屏幕外位图。

When canvas.restore() is called, this bitmap is transferred to the on-screen canvas, and the alpha value we supplied in saveLayerAlpha(....) is applied to the off-screen bitmap.

(我认为),下面是不使用 saveLayerAlpha(....)创建这种效果的等效方式:

(I think) The following is an equivalent way of creating this effect without using saveLayerAlpha(....):

public class SView extends View {

    Paint paintColor, paintBorder, paintAlpha;

    Bitmap toDrawOn;

    public SView(Context context) {
        super(context);

        paintAlpha = new Paint();

        paintAlpha.setColor(Color.parseColor("#90FFFFFF"));
        paintAlpha.setAntiAlias(true);

        ....
        ....

    }

    @Override
    protected void onDraw(Canvas canvas) {

        if (toDrawOn == null) {

            // Create a new Bitmap
            toDrawOn = Bitmap.createBitmap(getWidth(), getHeight(), 
                                                    Config.ARGB_8888);

            // Create a new Canvas; drawing operations 
            // will happen on 'toDrawOn'
            Canvas offScreen = new Canvas(toDrawOn);

            // First circle
            paintColor.setColor(Color.RED);
            offScreenCanvas.drawCircle(getWidth() / 3, getHeight() / 2, 
                                           getWidth() / 4 - 20, paintColor);
            offScreenCanvas.drawCircle(getWidth() / 3, getHeight() / 2, 
                                           getWidth() / 4 - 15, paintBorder);

            // Second circle
            paintColor.setColor(Color.BLUE);
            offScreenCanvas.drawCircle(2 * getWidth() / 3, getHeight() / 2, 
                                           getWidth() / 4 - 20, paintColor);
            offScreenCanvas.drawCircle(2 * getWidth() / 3, getHeight() / 2, 
                                           getWidth() / 4 - 15, paintBorder);

            // Draw bitmap 'toDrawOn' to canvas using 'paintAlpha'
            canvas.drawBitmap(toDrawOn, 0, 0, paintAlpha);

        } else {

            // 'toDrawOn' is not null; draw it
            canvas.drawBitmap(toDrawOn, 0, 0, paintAlpha);
        }
    }
}

输出:

仅供参考,上面的图像中的基本容器是的LinearLayout 背景设置为此JPEG:<一href="http://images1.pixlis.com/background-image-horizontal-lines-and-stripes-seamless-tileable-black-white-22h8w7.png">Link.

Just for reference, the base container in the image above is a LinearLayout with background set to this jpeg: Link.

和,作为SampleView的背景绘制:

And, the drawable used as the background of SampleView:

// Just a random image to 'see' the difference
setBackground(getResources().getDrawable(R.drawable.hor_lines));

摘自:这里

这篇关于Android的自定义视图不处理透明度/阿尔法的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆