您的位置:首页 > Web前端

自定义view之PorterDuffXfermode实现刮刮卡

2015-11-12 15:38 465 查看
首先 先来看看刮刮卡的实现demo吧



效果棒棒哒!

在看代码之前,我们先来了解下PorterDuffXfermode。

PorterDuffXfermode

PorterDuffXfermode设置的是两个图层交集区域的显示方式,dst是先画的图形,而src是后画的图形。

当然,这些模式也不是经常使用的,用的最多的是,使用一张图片作为另一张图片的遮罩层,通过控制遮罩层的图形,来控制下面被遮罩图形的显示效果。其中最常用的就是通过DST_IN、SRC_IN模式来实现。



我们的刮刮卡也是通过这个原理实现的。在初始状态下,上面的图层会将下面整个图层覆盖,当你用手刮上面的图层的时候,下面的图层会慢慢显示出来,这也类似很多画图工具中的橡皮擦效果。

下面具体来分析实现原理。

首先需要做一些初始化工作,例如背景图、遮罩图和我们画图的Paint的一些属性,代码如下:

mPaint = new Paint();
mPaint.setAlpha(0);
//设置混合模式为DST_IN
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.mipmap.beauty);
//设置遮罩图
mFgBitmap = Bitmap.createBitmap(mBgBitmap.getWidth(),
mBgBitmap.getHeight(), Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mFgBitmap);
mCanvas.drawColor(Color.GRAY);


在上面的代码中,给Paint设置一些属性,让他的笔触和连接处更加圆滑一点,即Paint.Join.ROUND和Paint.Cap.ROUND属性。

将Paint的透明度设为0,这样才能显示出橡皮擦的效果,这是因为在使用PorterDuffXfermode进行图层混合时,并不是简单的只进行图层的计算,同事也会去计算透明通道的值。

接下来,看一下如何获取用户手指滑动所产生的路径。

@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;
}
mCanvas.drawPath(mPath, mPaint);
invalidate();
return true;
}


好了,到这里代码估计就清晰了。首先初始化了一张背景图和一张灰色的图,并且混合模式为DST_IN,在滑动的时候,上层的灰色变透明,下层的和上层的合并,就出现了类似的效果。

最后看一下全部代码:

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.example.cntvuser.myapplication.R;

public class XfermodeView extends View {

private Bitmap mBgBitmap, mFgBitmap;
private Paint mPaint;
private Canvas mCanvas;
private Path mPath;

public XfermodeView(Context context) {
super(context);
init();
}

public XfermodeView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}

public XfermodeView(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}

private void init() {
mPaint = new Paint();
mPaint.setAlpha(0);
//设置混合模式为DST_IN
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.mipmap.beauty);
//设置遮罩图
mFgBitmap = Bitmap.createBitmap(mBgBitmap.getWidth(),
mBgBitmap.getHeight(), Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mFgBitmap);
mCanvas.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;
}
mCanvas.drawPath(mPath, mPaint);
invalidate();
return true;
}

@Override
protected void onDraw(Canvas canvas) {
//画背景
canvas.drawBitmap(mBgBitmap, 0, 0, null);
//画灰色
canvas.drawBitmap(mFgBitmap, 0, 0, null);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: