简体   繁体   中英

How to correctly apply PorterDuff.Mode.MULTIPLY to a vector drawable in onDraw();

Inside the onDraw() method in my custom View, I am trying to overlay a rectangle on top of a vector drawable. The desired effect is for the top part of the eye to be violet, and the bottom part to remain grey, and the background to remain dark grey. To achieve this effect I'm using the PorterDuff.Mode.MULTIPLY.

Unfortunately, the effect that I am achieving is incorrect (the background of the vector drawable is affected, as if it didn't recognize it as a path):

将 Rect 覆盖在 VectorDrawable 上的示例

Here is my code:

public class EyeStatusIcon extends View {

    private Rect canvasRect = null;
    private Rect colorMask = null;
    private Drawable eyeIcon;
    private Paint maskPaint;

    public EyeStatusIcon(Context c){
        this(c,null);
    }

    public EyeStatusIcon(Context c, AttributeSet s) {
        super(c, s);

        eyeIcon = c.getDrawable(R.drawable.illustration_eye_open);

        maskPaint = new Paint();
        maskPaint.setStyle(Paint.Style.FILL);
        maskPaint.setColor(c.getColor(R.color.accent));

        maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        eyeIcon.setBounds(canvasRect.left, canvasRect.top, canvasRect.right, canvasRect.bottom);
        eyeIcon.draw(canvas);
        canvas.drawRect(colorMask, maskPaint);


    }

    @Override
    protected void onSizeChanged(int newW, int newH, int oldW, int oldH) {
        canvasRect = new Rect(0, 0, newW, newH);
        colorMask = new Rect(0, 0, newW, newH/2);
        super.onSizeChanged(newW, newH, oldW, oldH);
    }
}

My question is, how can I apply PorterDuff blending (or another technique) in order to tint a part of my SVG-based, transparent-background Vector Drawable? Thank you!

I found a solution to my own problem by creating a second Canvas for the foreground, and cropping the bitmap (where it says getHeight()/2 ) drawn onto it. Hope this helps someone. This can be used to create a nice sliding courtain effect.

public class EyeStatusIcon extends View {

    private Rect canvasRect = null;
    private Drawable normalIcon, tintedIcon;

    private Canvas foregroundCanvas;
    private Bitmap foregroundBitmap;

    public EyeStatusIcon(Context c){
        this(c,null);
    }

    public EyeStatusIcon(Context c, AttributeSet s) {
        super(c, s);

        setLayerType(LAYER_TYPE_HARDWARE, null);

        normalIcon = c.getDrawable(R.drawable.illustration_eye_open);
        tintedIcon = c.getDrawable(R.drawable.illustration_eye_open);
        if(tintedIcon != null) tintedIcon.setTint(c.getColor(R.color.accent));

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        normalIcon.setBounds(canvasRect.left, canvasRect.top, canvasRect.right, canvasRect.bottom);
        tintedIcon.setBounds(canvasRect.left, canvasRect.top, canvasRect.right, canvasRect.bottom);

        normalIcon.draw(canvas);

        tintedIcon.draw(foregroundCanvas);
        canvas.drawBitmap(foregroundBitmap, 0, 0, null);

    }

    @Override
    protected void onSizeChanged(int newW, int newH, int oldW, int oldH) {
        canvasRect = new Rect(0, 0, newW, newH);

        foregroundBitmap = Bitmap.createBitmap(getWidth(), getHeight()/2, Bitmap.Config.ARGB_8888);
        foregroundBitmap.eraseColor(Color.TRANSPARENT);
        foregroundCanvas = new Canvas(foregroundBitmap);
        foregroundCanvas.drawColor(Color.argb(0, 0, 0, 0));

        super.onSizeChanged(newW, newH, oldW, oldH);
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM