Android实现刮刮卡抽奖(上)

自定义View实现刮刮卡界面:
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/**
* 自定义一个刮刮卡view
* @description:
* @date 2015-12-3 上午9:27:06
*/
@SuppressLint(“DrawAllocation”)
public class ScratchCardView extends View {

private Paint mPaint;// 画笔
private Path mPath;// 绘制路径
private Canvas mCanvas;// 画面Canvas
private int mCurrentX;// 手指移动后X位置
private int mCurrentY;// 手指移动后Y位置
private Bitmap mTopBitmap;// 位于上层图片
private String mTextStr;// 卡片上的文字
private Paint mTextPaint;// 画文字的画笔
private Rect mTextRect;// 文字对应的矩形框Rect
private volatile boolean isFinish = false;// 判断遮盖层是否被用户消除达到一定的范围(阙值)
private OnScratchCardFinishListener mCardFinishListener;//刮完成后回调接口
public interface OnScratchCardFinishListener {// 图层刮完后回调接口
    void onFinish(String result);
}
// 设置回调
public void setCardFinishListener(OnScratchCardFinishListener mCardFinish) {
    this.mCardFinishListener = mCardFinish;
}
public ScratchCardView(Context context) {
    this(context, null, 0);

}
public ScratchCardView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    initViewsParams();
}
public ScratchCardView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}
/**
 * 初始化相关数据及参数
 * @description:
 * @date 2015-12-3 上午9:26:48
 */
private void initViewsParams() {
    mPath = new Path();
    mPaint = new Paint();
    mTextStr = "500万现金";
    mTextPaint = new Paint();
    mTextRect = new Rect();
}
private void setTextPaint() {
    mTextPaint.setColor(Color.RED);// 设置颜色
    mTextPaint.setStyle(Style.FILL);// 设置画笔样式为填充
    mTextPaint.setTextSize(40);
    mTextPaint.getTextBounds(mTextStr, 0, mTextStr.length(), mTextRect);// 获得当前文字的宽高信息
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int width = getMeasuredWidth();// 获取到宽度
    int height = getMeasuredHeight();// 获取到高度
    mTopBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);// 根据参数创建新位图
    mCanvas = new Canvas(mTopBitmap);
    // 设置绘画文字的画笔 参数
    setTextPaint();
    // 设置画笔参数
    setBitmapPaint();
    mCanvas.drawColor(Color.parseColor("#c0c0c0"));
}
private void setBitmapPaint() {
    mPaint.setColor(Color.GREEN);// 设置颜色
    mPaint.setAntiAlias(true);// 设置抗紧锯齿
    mPaint.setDither(true);// 防抖动
    mPaint.setStrokeJoin(Paint.Join.ROUND);// 设置图形结合处的样子
    mPaint.setStrokeCap(Paint.Cap.ROUND);// 设置画笔的图形样式,如圆形样式
    mPaint.setStyle(Style.STROKE);// 设置画笔样式为空心
    mPaint.setStrokeWidth(20);// 设置画笔粗细
}
@Override
public boolean onTouchEvent(MotionEvent event) {
    int action = event.getAction();
    int x = (int) event.getX();// 当前x
    int y = (int) event.getY();// 当前y
    switch (action) {
        case MotionEvent.ACTION_DOWN:
            mCurrentX = x;
            mCurrentY = y;
            mPath.moveTo(mCurrentX, mCurrentY);// 移动Path
            break;
        case MotionEvent.ACTION_MOVE:
            int dx = Math.abs(x - mCurrentX);
            int dy = Math.abs(y - mCurrentY);
            if (dx > 3 || dy > 3) {
                mPath.lineTo(x, y);
            }
            mCurrentX = x;
            mCurrentY = y;
            break;
        case MotionEvent.ACTION_UP:
            new Thread(mCardRunble).start();//开启子线程进行计算
            break;

        default:
            break;
    }
    invalidate();//主线程中调用invalidate()请求重绘View树,即draw()过程
    return true;
}

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawText(mTextStr, getWidth() / 2 - mTextRect.width() / 2, getHeight() / 2 + mTextRect.height() / 2, mTextPaint);
    if (!isFinish) {
        mPaint.setXfermode(new PorterDuffXfermode(Mode.DST_OUT));// ProterDuffXfermode用法可以参考:http://www.2cto.com/kf/201504/388144.html
        mCanvas.drawPath(mPath, mPaint);
        canvas.drawBitmap(mTopBitmap, 0, 0, null);
    }
    else {
        if (mCardFinishListener != null) {
            mCardFinishListener.onFinish(mTextStr);
        }
    }
}

private Runnable mCardRunble = new Runnable() {
    @Override
    public void run() {
        int w = getWidth();
        int h = getHeight();
        float wipeArea = 0;
        float totalArea = w * h;
        Bitmap bitmap = mTopBitmap;
        int[] mpixels = new int[w * h];

        bitmap.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 * 100 / totalArea);// 获取百分比
            if (percent > 60) {
                isFinish = true;
                postInvalidate();//子线程中调用invalidate()请求重绘View树,即draw()过程
            }
        }
    }
};

}
在Activity中使用,关键是要回调刮奖完毕的回调接口OnScratchCardFinishListener中的方法:
public class MainActivity extends Activity {
private ScratchCardView mCardView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mCardView = (ScratchCardView) findViewById(R.id.card_view);
    mCardView.setCardFinishListener(new OnScratchCardFinishListener() {
        @Override
        public void onFinish(String result) {
            Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();//回调时把显示的文字也Toast出来!
        }
    });
}

}

布局很简单,就是加了一个我们自定义的ScrtchCardView:

你可能感兴趣的:(android,view,自定义view)