如何正确地将 PorterDuff.Mode.MULTIPLY 应用于 onDraw() 中的矢量可绘制对象;
How to correctly apply PorterDuff.Mode.MULTIPLY to a vector drawable in onDraw();
在我的自定义视图的 onDraw() 方法中,我试图在矢量可绘制对象上叠加一个矩形。期望的效果是眼睛的顶部为紫色,底部保持灰色,背景保持深灰色。为了达到这种效果,我使用了 PorterDuff.Mode.MULTIPLY.
不幸的是,我实现的效果不正确(矢量绘图的背景受到影响,好像它没有将其识别为路径):
这是我的代码:
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);
}
}
我的问题是,如何应用 PorterDuff 混合(或其他技术)来为基于 SVG 的透明背景 Vector Drawable 的一部分着色?
谢谢!
我通过为前景创建第二个 Canvas 并裁剪绘制在其上的位图(其中显示 getHeight()/2
)找到了解决我自己问题的方法。希望这对某人有帮助。这可以用来创建一个漂亮的滑动庭院效果。
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);
}
}
在我的自定义视图的 onDraw() 方法中,我试图在矢量可绘制对象上叠加一个矩形。期望的效果是眼睛的顶部为紫色,底部保持灰色,背景保持深灰色。为了达到这种效果,我使用了 PorterDuff.Mode.MULTIPLY.
不幸的是,我实现的效果不正确(矢量绘图的背景受到影响,好像它没有将其识别为路径):
这是我的代码:
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);
}
}
我的问题是,如何应用 PorterDuff 混合(或其他技术)来为基于 SVG 的透明背景 Vector Drawable 的一部分着色? 谢谢!
我通过为前景创建第二个 Canvas 并裁剪绘制在其上的位图(其中显示 getHeight()/2
)找到了解决我自己问题的方法。希望这对某人有帮助。这可以用来创建一个漂亮的滑动庭院效果。
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);
}
}