canvas教程

Android自定义刮刮卡实现(2)

字号+ 作者:H5之家 来源:H5之家 2017-07-28 09:00 我要评论( )

这样我们就绘制好了背景层的中奖信息,再来就是前景层,和上面一样我们利用资源文件转Bitmap对象然后绑定Canvas并绘制上刮刮卡图案 //通过资源文件创建Bitmap对象mBitmap = BitmapFactory.decodeResource(getResour

这样我们就绘制好了背景层的中奖信息,再来就是前景层,和上面一样我们利用资源文件转Bitmap对象然后绑定Canvas并绘制上刮刮卡图案

//通过资源文件创建Bitmap对象 mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.background); //新建同等大小的Bitmap对象 mForeBitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Bitmap.Config.ARGB_8888); //双缓冲,装载画布 mForeCanvas = new Canvas(mForeBitmap); mForeCanvas.drawBitmap(mBitmap, 0, 0, null);

剩下的利用Path来记录用户手指触摸路径就是一样的了,这里我们额外来添加一个功能,使得当用户在刮刮卡上刮的区域范围超过50%后,自动消除刮刮卡前景层。

我们通过Bitmap的getPixels方法就可以拿到Bitmap的像素信息,由于这里涉及到了计算,这是个耗时操作,所以这里我们开启一个子线程来执行任务

private Runnable mRunnable = new Runnable() { int[] pixels; @Override public void run() { int w = mForeBitmap.getWidth(); int h = mForeBitmap.getHeight(); float wipeArea = 0; float totalArea = w * h; pixels = new int[w * h]; /** * pixels 接收位图颜色值的数组 * offset 写入到pixels[]中的第一个像素索引值 * stride pixels[]中的行间距个数值(必须大于等于位图宽度)。可以为负数 * x  从位图中读取的第一个像素的x坐标值。 * y 从位图中读取的第一个像素的y坐标值 * width   从每一行中读取的像素宽度 * height    读取的行数 */ mForeBitmap.getPixels(pixels, 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 (pixels[index] == 0) { wipeArea++; } } } if (wipeArea > 0 && totalArea > 0) { int percent = (int) (wipeArea * 100 / totalArea); if (percent > 50) { isClear = true; postInvalidate(); } } } };

首先我们声明一个数组来记录像素点信息,数组的大小即为像素总数的大小也就是Bitmap的宽

高,然后我们在onTouchEvent里的ACTION_UP中去计算被擦除的像素值,这里的for循环可能有的朋友会看的有点懵,没着急,我画一张图,你就能懂。

Bitmap像素点


w,假设这个Bitmap的像素大小是3*3,那么index的值就是0,3,6,1,4,7,2,5,8,是不是有感觉了?我们遍历像素点是按照纵向下来的,当pixels的值为0的时候,证明已经是被用户擦除掉的像素点。

当被擦除的区域超出50%,我们就在onDraw里去控制不让canvas绘制前景图即可。

@Override protected void onDraw(Canvas canvas) { canvas.drawText(mText, mForeBitmap.getWidth() / 2 - mRect.width() / 2, mForeBitmap.getHeight() / 2 + mRect.height() / 2, mTextPaint); if (!isClear) { canvas.drawBitmap(mForeBitmap, 0, 0, null); } }

下面贴一下完整版的代码:

package com.lcw.view; import android.content.Context; 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.util.AttributeSet; import android.view.MotionEvent; import android.view.View; /** * 刮刮卡(完善版) * Create by: chenwei.li * Date: 2017/7/22 * Time: 下午7:25 * Email: lichenwei.me@foxmail.com */ public class ScratchCardView2 extends View { //处理文字 private String mText = "恭喜您中奖啦!!"; private Paint mTextPaint; private Rect mRect; //处理图层 private Paint mForePaint; private Path mPath; private Bitmap mBitmap;//加载资源文件 private Canvas mForeCanvas;//前景图Canvas private Bitmap mForeBitmap;//前景图Bitmap //记录位置 private int mLastX; private int mLastY; private volatile boolean isClear;//标志是否被清除 public ScratchCardView2(Context context) { this(context, null); } public ScratchCardView2(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ScratchCardView2(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { mRect = new Rect(); mPath = new Path(); //文字画笔 mTextPaint = new Paint(); mTextPaint.setAntiAlias(true); mTextPaint.setColor(Color.GREEN); mTextPaint.setStyle(Paint.Style.FILL); mTextPaint.setTextSize(30); mTextPaint.getTextBounds(mText, 0, mText.length(), mRect); //擦除画笔 mForePaint = new Paint(); mForePaint.setAntiAlias(true); mForePaint.setAlpha(0); mForePaint.setStrokeCap(Paint.Cap.ROUND); mForePaint.setStrokeJoin(Paint.Join.ROUND); mForePaint.setStyle(Paint.Style.STROKE); mForePaint.setStrokeWidth(30); mForePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); //通过资源文件创建Bitmap对象 mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.background); mForeBitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Bitmap.Config.ARGB_8888); //双缓冲,装载画布 mForeCanvas = new Canvas(mForeBitmap); mForeCanvas.drawBitmap(mBitmap, 0, 0, null); } @Override protected void onDraw(Canvas canvas) { canvas.drawText(mText, mForeBitmap.getWidth() / 2 - mRect.width() / 2, mForeBitmap.getHeight() / 2 + mRect.height() / 2, mTextPaint); if (!isClear) { canvas.drawBitmap(mForeBitmap, 0, 0, null); } } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mLastX = (int) event.getX(); mLastY = (int) event.getY(); mPath.moveTo(mLastX, mLastY); break; case MotionEvent.ACTION_MOVE: mLastX = (int) event.getX(); mLastY = (int) event.getY(); mPath.lineTo(mLastX, mLastY); break; case MotionEvent.ACTION_UP: new Thread(mRunnable).start(); break; default: break; } mForeCanvas.drawPath(mPath, mForePaint); invalidate(); return true; } /** * 开启子线程计算被擦除的像素点 */ private Runnable mRunnable = new Runnable() { int[] pixels; @Override public void run() { int w = mForeBitmap.getWidth(); int h = mForeBitmap.getHeight(); float wipeArea = 0; float totalArea = w * h; pixels = new int[w * h]; /** * pixels 接收位图颜色值的数组 * offset 写入到pixels[]中的第一个像素索引值 * stride pixels[]中的行间距个数值(必须大于等于位图宽度)。可以为负数 * x  从位图中读取的第一个像素的x坐标值。 * y 从位图中读取的第一个像素的y坐标值 * width   从每一行中读取的像素宽度 * height    读取的行数 */ mForeBitmap.getPixels(pixels, 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 (pixels[index] == 0) { wipeArea++; } } } if (wipeArea > 0 && totalArea > 0) { int percent = (int) (wipeArea * 100 / totalArea); if (percent > 50) { isClear = true; postInvalidate(); } } } }; } 源码下载:

这里附上源码地址(欢迎Star,欢迎Fork): 源码下载

分享给小伙伴们:

本文标签: Android,刮刮卡/">Android,刮刮卡

相关文章

发表评论愿您的每句评论,都能给大家的生活添色彩,带来共鸣,带来思索,带来快乐。

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • Android实现图片反转

    Android实现图片反转

    2017-07-28 15:04

  • 多分辨率适配常用目录

    多分辨率适配常用目录

    2017-07-25 18:00

  • 萌新学android之第二天—容易画板

    萌新学android之第二天—容易画板

    2017-07-22 17:01

  • 印度Micromax的A116 Canvas HD与Canvas Magnus A117可享Lollipop

    印度Micromax的A116 Canvas HD与Canvas Magnus A117可享Lollipop

    2017-07-22 08:01

网友点评