Android自定义视图无法以正确的方式处理透明度/ alpha

时间:2013-11-27 22:46:13

标签: java android android-custom-view alpha

我正在绘制自定义视图。在此视图中,我使用两个不同的绘制和路径对象绘制到画布。我基本上画了两个重叠的形状。添加alpha后,视图中重叠的部分比图像的其余部分更暗。这是不受欢迎的,但我不确定如何解决它。

这是我的代码的剪辑,以显示我在NewButtonView.java中如何使用alpha

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);

这个Google I/O video大约31分钟......它们显示了我想要的效果。

他们基本上显示这个图像: enter image description here

添加透明度并获取此图片:UNDESIRED RESED

enter image description here

他们最终得到了这个:渴望的结果

enter image description here

有没有人知道如何获得这种理想的效果?

2 个答案:

答案 0 :(得分:12)

如视频中所述,您可以使用Canvas#saveLayerAlpha(....)。您也可以在不使用它的情况下获得类似的效果。我稍后会讨论。

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

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();
    }
}

会发生什么:

  1. 调用saveLayerAlpha(....)时会分配屏幕外位图。

  2. 所有绘图操作都在此位图上进行。

  3. 调用canvas.restore()时,此位图将传输到屏幕画布,我们在saveLayerAlpha(....)中提供的Alpha值将应用于屏幕外位图。

  4. (我认为)以下是在不使用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);
            }
        }
    }
    

    <强>输出:

    enter image description here

    仅供参考,上图中的基本容器为LinearLayout,背景设置为此jpeg:Link

    并且,drawable用作SampleView的背景:

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

    取自:here

答案 1 :(得分:0)

您可以使用完整的alpha绘制位图中的所有内容,然后更改位图的alpha

(对不起,这是一个评论而非答案,但堆栈溢出不允许我发表评论)