package com.bigfat.guaguaka.view; import android.content.Context; import android.content.res.TypedArray; 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.graphics.Rect; import android.graphics.RectF; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; import android.view.MotionEvent; import android.view.View; import com.bigfat.guaguaka.R; /** * @author <a href="mailto:fbzhh007@gmail.com">bigfat</a> * @since 2015/2/14 */ public class GuaGuaKa extends View { /** * 刮刮卡刮完的回调 */ public interface OnGuaGuaKaCompleteListener { void onComplete(); } private OnGuaGuaKaCompleteListener onGuaGuaKaCompleteListener; //刮刮卡覆盖层 private Paint mOuterPaint; private Path mPath; private Canvas mCanvas; private Bitmap mOuterBitmap;//”刮刮乐“封面 private Bitmap mBitmap;//整个覆盖层 //用户手指触摸的最后位置(即当前位置) private int mLastX; private int mLastY; //刮刮卡真实内容 //刮奖文本 private String mText; private int mTextSize; private int mTextColor; private Paint mTextPaint; //记录刮奖文本信息的宽高 private Rect mTextBound; //是否完成刮奖,即显示刮奖结果 private volatile boolean mIsComplete; private int mCornerRadius = 30; //计算刮开区域 private Runnable mRunnable = new Runnable() { @Override public void run() { int w = getWidth(); int h = getHeight(); float wipeArea = 0; float totalArea = w * h; //获得Bitmap上所有像素 int[] mPixels = new int[w * h]; mBitmap.getPixels(mPixels, 0, w, 0, 0, w, h); //计算已擦除像素 for (int i = 0; i < w; i++) { for (int j = 0; j < h; j++) { int index = i + j * w; if (mPixels[index] == 0) { wipeArea++; } } } //计算擦除/刮开百分比 if (wipeArea > 0 && totalArea > 0) { int percent = (int) (wipeArea / totalArea * 100); Log.i("TAG", "percent--->" + percent); //如果刮开区域超过60%,则直接显示全部 if (percent > 60) { mIsComplete = true; postInvalidate(); } } } }; 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 = context.getTheme().obtainStyledAttributes(attrs, R.styleable.GuaGuaKa, defStyleAttr, 0); int count = a.getIndexCount(); for (int i = 0; i < count; 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, Color.DKGRAY); break; case R.styleable.GuaGuaKa_textSize: mTextSize = (int) a.getDimension(attr, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 24, getResources().getDisplayMetrics())); break; } } a.recycle(); } public void setText(String text) { this.mText = text; } public void setOnGuaGuaKaCompleteListener(OnGuaGuaKaCompleteListener onGuaGuaKaCompleteListener) { this.onGuaGuaKaCompleteListener = onGuaGuaKaCompleteListener; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = getMeasuredWidth(); int height = getMeasuredHeight(); //初始化画布 mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); // mCanvas.drawColor(0xffc0c0c0); mCanvas.drawRoundRect(new RectF(0, 0, width, height), mCornerRadius, mCornerRadius, mOuterPaint); mCanvas.drawBitmap(mOuterBitmap, null, new RectF(0, 0, width, height), null); //设置画笔属性 setOuterPaint(); setTextPaint(); } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); int x = (int) event.getX(); int y = (int) event.getY(); switch (action) { case MotionEvent.ACTION_DOWN: mLastX = x; mLastY = y; mPath.moveTo(mLastX, mLastY); break; case MotionEvent.ACTION_MOVE: int dx = Math.abs(x - mLastX); int dy = Math.abs(y - mLastY); if (dx > 3 || dy > 3) { mPath.lineTo(x, y); } mLastX = x; mLastY = y; break; case MotionEvent.ACTION_UP: new Thread(mRunnable).start(); break; } invalidate(); return true; } @Override protected void onDraw(Canvas canvas) { // canvas.drawBitmap(bitmap, 0, 0, null); //刮奖信息 canvas.drawText(mText, getWidth() / 2 - mTextBound.width() / 2, getHeight() / 2 + mTextBound.height() / 2, mTextPaint); if (mIsComplete) { if (onGuaGuaKaCompleteListener != null) { onGuaGuaKaCompleteListener.onComplete(); } } else { //刮开区域 drawPath(); canvas.drawBitmap(mBitmap, 0, 0, null); } } /** * 绘制覆盖层刮开的路径 */ private void drawPath() { mOuterPaint.setStyle(Paint.Style.STROKE); mOuterPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); mCanvas.drawPath(mPath, mOuterPaint); } private void init() { mOuterPaint = new Paint(); mPath = new Path(); mOuterBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.fg_guaguaka); mTextPaint = new Paint(); mTextBound = new Rect(); mText = "谢谢惠顾"; mTextColor = Color.DKGRAY; mTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 24, getResources().getDisplayMetrics()); } /** * 设置覆盖层画笔属性 */ private void setOuterPaint() { mOuterPaint.setColor(0xffc0c0c0); mOuterPaint.setAntiAlias(true); mOuterPaint.setDither(true); mOuterPaint.setStrokeJoin(Paint.Join.ROUND); mOuterPaint.setStrokeCap(Paint.Cap.ROUND); mOuterPaint.setStyle(Paint.Style.FILL); mOuterPaint.setStrokeWidth(36); } /** * 设置刮奖信息画笔属性 */ private void setTextPaint() { mTextPaint.setColor(mTextColor); mTextPaint.setStyle(Paint.Style.FILL); mTextPaint.setTextSize(mTextSize); //获得当前画笔绘制文本的宽高 mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBound); } }