Android 刮刮卡原理
个人做个记录,无意从研发变成了产品,现在回头做做代码,练练生手。只看刮的原理,很简单。需要知道的核心就1个:Paint.setXfermode。基本原理:
- 一共分两层,如下图,上面一层用于刮,下面一层用于显示。演示代码为偷懒的方式用两个控件层叠,实际应该使用自定义控件绘制。
- 刮奖层在触摸时,使用Paint.setXfermode在刮奖层绘制,达到部分透明的目的。
动手:1. 布局,就类似上图,两个控件层叠(实际请自行绘制自定义控件,如代码本来应该只有GuaGuaCard)<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ScrollingActivity"> <TextView android:layout_width="300dp" android:layout_height="300dp" android:gravity="center" android:text="5000" android:textSize="100dp" /> <com.mc.wiget.GuaGuaCard android:layout_width="300dp" android:layout_height="300dp" /> </FrameLayout>
2. 创建刮奖层自定义控件刮奖层自定义控件的原理是,创建一个灰色的图片绘制到canvas,在触摸事件中不端的使用Path在图片上绘制“擦除区域”,实际是Xfermode的dst_out模式。1)初始化绘制蒙层的画笔/** * 初始化画笔 */ private void init() { mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); //导致擦除效果的核心 mPaint.setColor(Color.BLACK); mPaint.setAntiAlias(true); mPaint.setStrokeWidth(40); mPaint.setStyle(Paint.Style.STROKE); mPath = new Path(); }
2)绘制好基本的蒙层@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //测量蒙层大小,并初始化 mFrontGround = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888); //将蒙层绘制到刮奖区域 mFrontCanvas = new Canvas(mFrontGround); mFrontCanvas.drawColor(Color.BLUE); }
3) 在手指移动时绘制擦除区域
@Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); float x = 0; float y = 0; switch (action) { //按下时移动擦除的起点到手指落下的坐标 case MotionEvent.ACTION_DOWN: { x = event.getX(); y = event.getY(); mPath.moveTo(x, y); break; } //移动时绘制直线,即擦除区域 case MotionEvent.ACTION_MOVE: x = Math.abs(event.getX() - x); y = Math.abs(event.getY() - y); mPath.lineTo(x, y); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: default: break; } //绘制 invalidate(); return true; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //在刮奖区域上绘制擦除区域,因为用了xfermode,所以这块会是透明的 mFrontCanvas.drawPath(mPath, mPaint); //将刮奖区域绘制到控件上展示 canvas.drawBitmap(mFrontGround, 0, 0, null); }
这样基本就能够把刮奖层搞定,那后面的,要是一时想不清楚,可以尝试 源码下载。