Android 使用Xfermode 自定义View实现刮刮卡

ScratchCardView.class

package com.hbz.core.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.hbz.core.R;

public class ScratchCardView extends View {

    protected int textColor;
    protected int coatingColor;
    protected float textSize;
    protected float eraserSize;
    protected String text;
    protected Path path;
    protected int width;
    protected int height;
    protected Bitmap coatingBitmap;
    protected Canvas coatingCanvas;
    protected Paint textPaint;
    protected Paint eraserPaint;
    protected float pointX;
    protected float pointY;
    protected boolean isComplete;
    private float percentage;
    private Bitmap backgroundBitmap;
    private Matrix matrix;

    public ScratchCardView(Context context) {
        this(context, null);
    }

    public ScratchCardView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ScratchCardView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ScratchCardView);
        textColor = array.getColor(R.styleable.ScratchCardView_textColor, Color.BLACK);
        coatingColor = array.getColor(R.styleable.ScratchCardView_coatingColor, Color.GRAY);
        textSize = array.getDimension(R.styleable.ScratchCardView_textSize, 25);
        eraserSize = array.getDimension(R.styleable.ScratchCardView_eraserSize, 20);
        text = array.getString(R.styleable.ScratchCardView_text);
        percentage = array.getFloat(R.styleable.ScratchCardView_percentage, 70);
        BitmapDrawable backgroundImg = (BitmapDrawable) array.getDrawable(R.styleable.ScratchCardView_backgroundImg);
        if (backgroundImg != null) {
            backgroundBitmap = backgroundImg.getBitmap();
        }
        array.recycle();
        initPaint();
    }

    protected void initPaint() {
        textPaint = new Paint();
        textPaint.setAntiAlias(true);
        textPaint.setStyle(Paint.Style.FILL);
        textPaint.setStrokeWidth(20);
        textPaint.setTextSize(textSize);
        textPaint.setDither(true);
        textPaint.setColor(textColor);
        eraserPaint = new Paint();
        eraserPaint.setAntiAlias(true);
        eraserPaint.setStyle(Paint.Style.STROKE);
        eraserPaint.setStrokeWidth(10);
        eraserPaint.setTextSize(eraserSize);
        eraserPaint.setDither(true);
        path = new Path();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = w;
        height = h;
        initBackground();
        coatingBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        coatingCanvas = new Canvas(coatingBitmap);
        coatingCanvas.drawColor(coatingColor);
    }

    @Override
    public void draw(Canvas canvas) {
        if (backgroundBitmap != null) {
            canvas.drawBitmap(backgroundBitmap, matrix, null);
        }
        drawText(canvas);
        if (!isComplete) {
            drawPath();
            canvas.drawBitmap(coatingBitmap, 0, 0, null);
        }
        super.draw(canvas);
    }

    protected void initBackground() {
        matrix = new Matrix();
        float bitmapWidth = backgroundBitmap.getWidth();
        float bitmapHeight = backgroundBitmap.getHeight();
        float scaleX = width / bitmapWidth;
        float scaleY = height / bitmapHeight;
        matrix.setScale(scaleX, scaleY);
    }

    private void drawPath() {
        //在涂层和path相交的地方,根据涂层的alpha进行过滤,
        eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
        coatingCanvas.drawPath(path, eraserPaint);
    }

    protected void drawText(Canvas canvas) {
        Rect rect = new Rect();
        textPaint.getTextBounds(text, 0, text.length(), rect);
        int textWidth = rect.width();
        int textHeight = rect.height();
        float x = width / 2 - textWidth / 2;
        float y = height / 2 + textHeight / 2;
        canvas.drawText(text, x, y, textPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                float downX = event.getX();
                float downY = event.getY();
                path.moveTo(downX, downY);
                invalidate();
                pointX = downX;
                pointY = downY;
                break;
            case MotionEvent.ACTION_MOVE:
                float moveX = event.getX();
                float moveY = event.getY();
                path.quadTo(pointX, pointY, moveX, moveY);
                invalidate();
                pointX = moveX;
                pointY = moveY;
                break;
            case MotionEvent.ACTION_UP:
                new Thread(mRunnable).start();
                break;
        }

        return true;
    }

    // 统计刮开的区域
    private Runnable mRunnable = new Runnable() {
        private int[] mPixels;

        @Override
        public void run() {
            int w = getWidth();
            int h = getHeight();
            float wipeArea = 0;
            float totalArea = w * h;
            Bitmap bitmap = coatingBitmap;
            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 > percentage) {
                    isComplete = true;
                    postInvalidate();
                }
            }
        }
    };
}

 

attr.xml 中添加

<declare-styleable name="ScratchCardView">
    <attr name="text" format="string" />
    <attr name="textSize" format="dimension" />
    <attr name="textColor" format="color" />
    <attr name="coatingColor" format="color" />
    <attr name="eraserSize" format="dimension" />
    <attr name="percentage" format="float" />
    <attr name="backgroundImg" format="reference" />
</declare-styleable>

布局中引用

<com.hbz.core.widget.ScratchCardView
    android:layout_width="120dp"
    android:layout_height="30dp"
    app:backgroundImg="@mipmap/delta"
    app:coatingColor="@color/rule_gray_hint"
    app:eraserSize="20dp"
    app:percentage="70"
    app:text="恭喜中奖"
    app:textColor="@color/color_red"
    app:textSize="14sp" />

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值