自定义view之刮刮乐

package com.bwie.chentong.guaguale;

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;

/**
 * Created by lenovo on 2017/9/28.
 */

public class GuaGuaView extends View{
    private String mText;
    private Rect mTextRect;
    private Paint mTextPaint;
    private int mTextSize;
    private int mTextColor;

    private Paint mTopPaint;
    private Bitmap topBitmap;
    private Canvas mCanvas;

    //手指的路径
    private Path mPath;
    //手指上次停留的位置
    private float mLastX;
    private float mLastY;

    private volatile boolean mIsComplete = false;
    private OnGuaGuaCompleteListener onGuaGuaCompleteListener;
    private PorterDuffXfermode porterDuffXfermode;

    public void setOnGuaGuaCompleteListener(OnGuaGuaCompleteListener onGuaGuaCompleteListener) {
        this.onGuaGuaCompleteListener = onGuaGuaCompleteListener;
    }

    /**
     * 抬起手指时,若刮开区域大于阈值,给用户提示
     */
    public interface OnGuaGuaCompleteListener {
        void onComplete();
    }

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

    public GuaGuaView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

        TypedArray typedArray = null;
        try {
            typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.GuaGuaView, defStyleAttr, 0);

            int indexCount = typedArray.getIndexCount();
            for (int i = 0; i < indexCount; i++) {
                int attr = typedArray.getIndex(i);
                switch (attr) {
                    case R.styleable.GuaGuaView_text:
                        mText = typedArray.getString(attr);
                        break;
                    case R.styleable.GuaGuaView_textSize:
                        //22sp转化为像素值
                        mTextSize = (int) typedArray.getDimension(attr,
                                TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 22, getResources().getDisplayMetrics()));
                        break;
                    case R.styleable.GuaGuaView_textColor:
                        mTextColor = typedArray.getColor(attr, 0x000000);
                        break;
                }
            }
            mTextPaint.setColor(mTextColor);
            mTextPaint.setTextSize(mTextSize);
        } finally {
            if (typedArray != null)
                typedArray.recycle();
        }
    }

    private void init() {
        porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);
        mText = "谢谢惠顾";
        mTextRect = new Rect();
        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 22, getResources().getDisplayMetrics());
        mTextPaint.setStyle(Paint.Style.STROKE);

        mTopPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTopPaint.setColor(Color.parseColor("#c0c0c0"));
        mTopPaint.setStyle(Paint.Style.FILL);
        mTopPaint.setDither(true);
        mTopPaint.setStrokeCap(Paint.Cap.ROUND);
        mTopPaint.setStrokeJoin(Paint.Join.ROUND);
        mTopPaint.setStrokeWidth(30);

        mPath = new Path();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //获得文本的边界信息
        mTextPaint.getTextBounds(mText, 0, mText.length(), mTextRect);
        canvas.drawText(mText, getWidth() / 2 - mTextRect.width() / 2, getHeight() / 2 + mTextRect.height() / 2, mTextPaint);

        if (!mIsComplete) {
            mTopPaint.setStyle(Paint.Style.STROKE);
            //只在源图像和目标图像相交的地方绘制透明
            mTopPaint.setXfermode(porterDuffXfermode);
            mCanvas.drawPath(mPath, mTopPaint);
            //还原混合模式
            mTopPaint.setXfermode(null);

            canvas.drawBitmap(topBitmap, 0, 0, null);
        } else {
            if (onGuaGuaCompleteListener != null) {
                onGuaGuaCompleteListener.onComplete();
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mLastX = event.getX();
                mLastY = event.getY();
                mPath.moveTo(event.getX(), event.getY());
                break;
            case MotionEvent.ACTION_MOVE:
                float dx = Math.abs(event.getX() - mLastX);
                float dy = Math.abs(event.getY() - mLastY);
                //手指移动的距离过小,不擦除
                if (dx > 5 || dy > 5) {
                    mLastX = event.getX();
                    mLastY = event.getY();
                    mPath.lineTo(mLastX, mLastY);
                }
                if (!mIsComplete) {
                    invalidate();
                }
                break;
            case MotionEvent.ACTION_UP:
                if (!mIsComplete) {
                    new Thread(mRunnable).start();
                }
                break;
        }
        return true;
    }

    private Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            int width = getWidth();
            int height = getHeight();

            int[] pixels = new int[width * height];
            float wipeArea = 0;
            float totalArea = width * height;

            /**
             * getPixels()函数把一张图片,从指定的偏移位置(offset),指定的位置(x,y)截取指定的宽高(width,height)
             * 把所得图像的每个像素颜色转为int值,存入pixels。
             * stride 参数指定在行之间跳过的像素的数目。图片是二维的,存入一个一维数组中,那么就需要这个参数来指定多少个像素换一行。
             * 详见:http://blog.csdn.net/xx326664162/article/details/52240795
             */
            topBitmap.getPixels(pixels, 0, width, 0, 0, width, height);

            for (int i = 0; i < width; i++) {
                for (int j = 0; j < height; j++) {
                    int index = i + j * width;
                    if (pixels[index] == 0) {
                        wipeArea++;
                    }
                }
            }

            float progress = wipeArea / totalArea;
            Log.d("test", "progress-----" + progress);
            if (progress > 0.6) {
                mIsComplete = true;
                postInvalidate();
            }

        }
    };

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        topBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(topBitmap);
        Bitmap bottomBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.timg6);
        //将图片以合适比例显示
        //先画灰色背景,再画图片
        mCanvas.drawRoundRect(new RectF(0, 0, w, h), 50, 50, mTopPaint);

        /**
         * bitmap 要绘制的位图对象
         * src 要裁切的位置,若是null则显示整张图片
         * dst 裁切后的图片显示的区域
         * paint 画笔
         */
        mCanvas.drawBitmap(bottomBitmap, null, new RectF(0, 0, w, h), null);
    }

    //设置中奖信息
    public void setText(String mText) {
        this.mText = mText;
    }

}
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可 6私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值