PorterDuffXfermode 丰富我们的绘图效果,PorterDuffXfermode 设置的是两个图层交集区域的显示方式,dst是先画的图形,而src是后话的图形;这里,使用一张图片作为另一张图片的遮罩层,通过控制遮罩层的图形,来控制下面被遮罩图形的显示效果。其中最常用的就是通过 DST_IN 、SRC_IN模式来京一个矩形图片变成圆角图片或者圆形图片的效果。
刮刮卡一般有两个图层,即上面用来被挂掉的图层和下面异常的图层。在初始状态下,上面的图层会将下面整个
图层覆盖,当你用手刮上面的图层的时候,下面的图层户慢慢显示出来,也像橡皮擦效果。使用PorterDuffXfermode 来实现
效果图:
首先做一下初始化工作,准备好图片,设置好Paint的一些属性,mPaint的一些设置
然后看一下,如何获取用户手指滑动所产生的的路径, 代码如下,使用path保存用户手指划过的路径。当然如果使用
贝塞尔曲线来做优化则会得到更好的显示效果,这里简单显示,就不用贝塞尔曲线了。
switch
(event.getAction()) {
case
MotionEvent.
ACTION_DOWN
:
mPath
.reset();
mPath
.moveTo(event.getX(), event.getY());
break
;
case
MotionEvent.
ACTION_MOVE
:
mPath
.lineTo(event.getX(), event.getY());
break
;
}
最后,只需要使用DST_IN模式将路径绘制到前面覆盖的图层上即可。不过,还需要做最关键的一步,那就是将画笔的透明度
设置为 0 ,这样才能显示出擦除的效果。很多读者可能不太理解这里将透明度设置为0的原因,这是因为在使用PorterDuffXfermode 进行图层混合时,并不是简单的只进行图层的计算,同时也会去计算透明通道的值。正是由于混合了透明通道才形成了这样的效果。
public class
GuaGuaView
extends
View {
private
Bitmap
mBgBitmap
,
mFgBitmap
;
private
Paint
mPaint
;
private
Canvas
canvas
;
private
Path
mPath
;
public
GuaGuaView(Context context) {
super
(context);
}
public
GuaGuaView(Context context, AttributeSet attrs) {
super
(context, attrs);
init(context);
}
public void
init(Context context) {
mPaint
=
new
Paint();
mPaint
.setAlpha(
0
);
mPaint
.setXfermode(
new
PorterDuffXfermode(PorterDuff.Mode.
DST_IN
));
mPaint
.setStyle(Paint.Style.
STROKE
);
mPaint
.setStrokeJoin(Paint.Join.
ROUND
);
mPaint
.setStrokeWidth(
50
);
mPaint
.setStrokeCap(Paint.Cap.
ROUND
);
mPath
=
new
Path();
//
原图不可以随意进行操作 ,所以需要复制一个原图出来
mBgBitmap
= BitmapFactory.
decodeResource
(getResources(), R.drawable.
test
);
mFgBitmap
= Bitmap.
createBitmap
(
mBgBitmap
.getWidth(),
mBgBitmap
.getHeight(), Bitmap.Config.
ARGB_8888
);
canvas
=
new
Canvas(
mFgBitmap
);
canvas
.drawColor(Color.
GRAY
);
}
@Override
public boolean
onTouchEvent(MotionEvent event) {
switch
(event.getAction()) {
case
MotionEvent.
ACTION_DOWN
:
mPath
.reset();
mPath
.moveTo(event.getX(), event.getY());
break
;
case
MotionEvent.
ACTION_MOVE
:
mPath
.lineTo(event.getX(), event.getY());
break
;
}
canvas
.drawPath(
mPath
,
mPaint
);
invalidate();
return true
;
}
@Override
protected void
onDraw(Canvas canvas) {
canvas.drawBitmap(
mBgBitmap
,
0
,
0
,
null
);
canvas.drawBitmap(
mFgBitmap
,
0
,
0
,
null
);
}
}