自定义view系列---刮刮乐的实现

本篇我们将通过另一个案例–刮刮乐 的实现来加深我们上节讲述的位图运算的理解。
我们先来分析下刮刮乐的实现思路:从技术实现上来说,刮刮乐有两个图层,一个是不会变化的中奖信息图层,一个是蒙上了一层灰色的图层。当用户手指在屏幕上涂抹时,需要将灰色抹掉,露出下面的中奖信息。

所以对于中奖信息来说,应该采用更简单的实现,可以在在图片上写上中奖信息后作为view的背景,当手指在屏幕上涂抹时就不需要考虑中奖信息的重绘了。然后在创建一个Bitmap对象,开始时是灰色的,手指在屏幕上移动时绘制线条,将线条与灰色做 Mode.CLEAR运算,相交的部分即被清除,变为透明效果,于是我们就能看到背景了。

以上过程总结为如下2个步骤
1,绘制背景
背景是一张图片,上面写上了中奖信息文字的。我们从本地资源中加载一张图片,是不能在向这张图片中添加信息的(没有设置可编辑标识),如果强制编辑,会报
java.lang.IllegalStateException: Immutable bitmap passed to Canvas constructor异常。
所以需要copy一份背景图片的bitmap,然后添加中奖文字后,调用view的public方法 setBackground将其设置为view的背景。

2,绘制遮挡中奖信息的蒙版,并处理手指移动逻辑
定义一个Bitmap,初始画上一层灰色,当手指在屏幕上移动时,绘制曲线,将曲线和灰色做Mode.CLEAR运算,实现清除的效果。

//1.绘制背景
private void drawBackground(){
		//1.1 加载背景图片
        Bitmap bgBmp = BitmapFactory.decodeResource(getResources(), R.mipmap.background);
        //1.2 copy背景图片并添加 Mutable为true标识
        Bitmap bgBmpCopy = bgBmp.copy(Bitmap.Config.ARGB_8888,true);
        Canvas bgCanvas = new Canvas(bgBmpCopy);
		//1.3 获取随机的中奖信息
        String text = PRIZE[random.nextInt(PRIZE.length)];
		//1.4 获取中奖信息文字的宽度和高度
        Rect rect = new Rect();
        paint.getTextBounds(text,0,text.length(),rect);
		//1.5 计算 中奖文字 绘制的开始位置(在背景图片的正中间)
        int x = (bgBmpCopy.getWidth() - rect.width()) / 2;
        int y = (bgBmpCopy.getHeight() - rect.height()) / 2 ;
		//1.6 将 中奖文字 绘制到背景的图层上
        bgCanvas.drawText(text,Math.max(x,0),Math.max(y,0),paint);
		//1.7 将处理好的背景图 设置view的Background
        setBackground(new BitmapDrawable(getResources(),bgBmpCopy));

    }
    private static final String PRIZE[] = {
      "恭喜,你中了一等奖,奖金 1 亿元",
      "恭喜,你中了二等奖,奖金 5000 万",
      "恭喜,你中了三等奖,奖金 100 元",
      "很遗憾,你没有中奖,继续加油哦"
    };

//2.绘制灰色蒙版遮挡view背景上的中奖信息
private Bitmap bmpBuffer;
private Canvas bufferCanvas;
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawBitmap(bmpBuffer, 0,0,null);//将灰色的bitmao绘制到view的canvas上
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
 super.onSizeChanged(w, h, oldw, oldh);

  bmpBuffer = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
  bufferCanvas = new Canvas(bmpBuffer);
  bufferCanvas.drawColor(Color.parseColor("#ff808080"));//灰色Bitmap
}

经过上述操作,view加载起来是如下效果:这块灰色区域就是我们自定义的view
在这里插入图片描述
下面就来处理在view上滑动绘制曲线,将灰色的蒙版清除,渐渐露出后面的中奖信息

//关键是要在view的构造方法中构造一个clearpaint对象,并设置该画笔的模式是Mode.CLEAR
private Paint paint, clearPaint;
private final  int FINGER = 50;
public GugGuaLeView(Context context, @Nullable AttributeSet attrs) {
     super(context, attrs);
     random = new Random();

     paint = new Paint(Paint.ANTI_ALIAS_FLAG);
     paint.setTextSize(50);
     paint.setColor(Color.RED);

     clearPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
     clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
     clearPaint.setStrokeJoin(Paint.Join.ROUND);
     clearPaint.setStrokeCap(Paint.Cap.ROUND);
     clearPaint.setStrokeWidth(FINGER);

     drawBackground();

 }
 
 //然后在view的onTouchevent中处理手指滑动绘制曲线的逻辑
 @Override
 public boolean onTouchEvent(MotionEvent event) {

     int action = event.getAction();
     int x = (int) event.getX();
     int y = (int) event.getY();
     switch (action){
         case MotionEvent.ACTION_DOWN:
             curtX = x;
             curtY = y;
             break;

         case MotionEvent.ACTION_MOVE:
             bufferCanvas.drawLine(curtX,curtY,x, y, clearPaint);//绘制手指滑动的路径,使用cleanPaint
             invalidate();
             curtX = x ;
             curtY = y;
             break;

         case MotionEvent.ACTION_UP:
             invalidate();
             break;
     }
     return true;
 }

现在我们随意在view上滑动,效果如下:可以看到我们view背景上的中奖信息随着手指滑动慢慢露出来了。
在这里插入图片描述
DONE
此系列后续持续更新。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值