Android - 刮刮卡
参考转载至 慕课网 《Android电商活动中的刮刮卡 http://www.imooc.com/view/225》
1、获取canvas 的两种途径
1)onDraw(Canvas canvas); 该回调方法由系统传参
2)new Canvan(mBitmap);
mBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mCanvas.drawBitmap(mOverlayBitmap,null,new Rect(0,0,getWidth(),getHeight()),null);
2、实现刮刮卡刮涂效果
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
Dst = 遮盖层,Src = 刮涂路径,DstOut 模式下刮涂路径的像素点值为零;

3、获取图片像素:bitmap.getPixels();
4、自定义View属性
1)values/attr.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="text" format="string"></attr>
<attr name="textColor" format="color"></attr>
<attr name="textSize" format="dimension"></attr>
<declare-styleable name="GuaGuaKa">
<attr name="text"></attr>
<attr name="textColor"></attr>
<attr name="textSize"></attr>
</declare-styleable>
</resources>
2) 获取自定义属性
private String mText; //中奖信息文本
private int mTextColor; //中奖信息文本颜色
private int mTextSize; //中奖信息文本大小
TypedArray a = null;
a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.GuaGuaKa, defStyleAttr, 0);
int n = a.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.GuaGuaKa_text:
mText = a.getString(attr);
break;
case R.styleable.GuaGuaKa_textColor:
mTextColor = a.getColor(attr, 0x000000);
break;
case R.styleable.GuaGuaKa_textSize:
mTextSize = (int) a.getDimension(attr, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 22, getResources().getDisplayMetrics()));
break;
}
}
if (a != null) a.recycle();
5、完整代码
public class GuaGuaKa extends View {
/*
自定义View属性
*/
private String mText; //中奖信息文本
private int mTextColor; //中奖信息文本颜色
private int mTextSize; //中奖信息文本大小
private Paint mTextPaint; //中奖信息画笔
private Paint mBrushPaint; //刮涂效果画笔
private Bitmap mBitmap; //刮涂效果图片
private Canvas mCanvas; //刮涂效果画布
private Rect mTextBound; //中奖信息文字区块
private Path mPath; //刮涂效果路径
private Bitmap mOverlayBitmap; //遮盖层图片
private float mLastX, mLastY;
private boolean mHasCompleted = false; //刮涂达到预定值既完成
/*
刮涂完成回调接口
*/
public interface OnCompletedListener {
void OnCompleted(String text);
}
private OnCompletedListener mOnCompletedListener;
public void setOnCompletedListener(OnCompletedListener listener) {
this.mOnCompletedListener = listener;
}
public GuaGuaKa(Context context) {
this(context, null);
}
public GuaGuaKa(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public GuaGuaKa(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(); //初始化
TypedArray a = null;
a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.GuaGuaKa, defStyleAttr, 0);
int n = a.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.GuaGuaKa_text:
mText = a.getString(attr);
break;
case R.styleable.GuaGuaKa_textColor:
mTextColor = a.getColor(attr, 0x000000);
break;
case R.styleable.GuaGuaKa_textSize:
mTextSize = (int) a.getDimension(attr, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 22, getResources().getDisplayMetrics()));
break;
}
}
if (a != null) a.recycle();
}
private void init(){
mText="谢谢惠顾";
mTextBound=new Rect();
mTextSize=(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,22,getResources().getDisplayMetrics());
mTextPaint=new Paint();
mBrushPaint=new Paint();
mPath=new Path();
mOverlayBitmap=BitmapFactory.decodeResource(getResources(),R.drawable.fg_guaguaka);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setUpTextPaint();
setUpOverlayPaint();
}
/*
设置绘制中奖信息所需对象
*/
private void setUpTextPaint() {
mTextPaint.setAntiAlias(true);
mTextPaint.setStyle(Paint.Style.STROKE);
mTextPaint.setTextSize(mTextSize);
mTextPaint.setColor(mTextColor);
//获得当前画笔绘制文本的宽与高
mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBound);
}
/*
设置绘制遮盖层所需对象
*/
private void setUpOverlayPaint() {
mBrushPaint.setAntiAlias(true);
mBrushPaint.setDither(true);
mBrushPaint.setStrokeJoin(Paint.Join.ROUND);
mBrushPaint.setStrokeCap(Paint.Cap.ROUND);
mBrushPaint.setStyle(Paint.Style.FILL);
mBrushPaint.setStrokeWidth(20);
mBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mCanvas.drawBitmap(mOverlayBitmap,null,new Rect(0,0,getWidth(),getHeight()),null);
mPath = new Path();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mPath.moveTo(x, y);
mLastX = x;
mLastY = y;
break;
case MotionEvent.ACTION_MOVE:
float dx = Math.abs(x - mLastX);
float dy = Math.abs(y - mLastY);
if (dx > 3.0f || dy > 3.0f) {
mPath.lineTo(x, y);
}
mLastX = x;
mLastY = y;
break;
case MotionEvent.ACTION_UP:
if (!mHasCompleted) {
if (calculateCompletedPercent() >= 60) {
mHasCompleted = true;
postInvalidate();
//完成后回调
if (mOnCompletedListener != null) {
mOnCompletedListener.OnCompleted(mText);
}
}
}
break;
default:
return super.onTouchEvent(event);
}
if (!mHasCompleted) {
postInvalidate();
}
return true;
}
@Override
protected void onDraw(Canvas canvas) {
//绘制中奖信息文本
canvas.drawRect(10, 10, getWidth() - 10, getHeight() - 10, mTextPaint);
canvas.translate(getWidth() / 2, getHeight() / 2);
canvas.drawText(mText, -mTextBound.width() / 2, mTextBound.height() / 2, mTextPaint);
canvas.translate(-getWidth() / 2, -getHeight() / 2);
if (!mHasCompleted) {
//设置画笔刮涂效果
mBrushPaint.setStyle(Paint.Style.STROKE);
mBrushPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
//绘制刮涂路径
mCanvas.drawPath(mPath, mBrushPaint);
canvas.drawBitmap(mBitmap, 0, 0, null);
}
}
/*
计算刮涂完成百分比
*/
private int calculateCompletedPercent() {
int w = mBitmap.getWidth();
int h = mBitmap.getHeight();
float wipeArea = 0; //被擦除的像素
float totalArea = w * h; //所有像素
int percent = 0;
int[] pixels = new int[w * h];
//获得bitmap上所有像素信息
mBitmap.getPixels(pixels, 0, w, 0, 0, w, h);
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
int index = j * w + i;
if (pixels[index] == 0) {
wipeArea++;
}
}
}
if (wipeArea > 0 && totalArea > 0) {
percent = (int) (wipeArea * 100 / totalArea);
}
return percent;
}
}
浙公网安备 33010602011771号