Android项目刮刮奖详解(一)

前言

最近正在学鸿洋大大的刮刮奖,感受学有所得,即是来写篇详解(尽管网上有不少了,不过毕竟是本身写的,本身之后方便复习),正文开始html

目标

实现画板功能canvas

思路

咱们须要自定义View来实现画板功能,以后再将其稍微改造便可。
关于自定义View,若是没有了解的同窗建议先去了解一下,百度自定义View就会有许多相关教程了,
我在这里也就简单的提一下,自定义View经常使用的三大类,Paint(画笔),Path(路径),
Canvas(画布),三大类方法介绍ide

  1. 继承View,实现构造方法测试

    四个构造方法,咱们主要实现两个参数的构造方法便可code

    private Paint mOutterPaint = new Paint(); // 绘制线条的Paint,即用户手指绘制Path
     private Path mPath = new Path();//记录用户绘制的Path
     private Canvas mCanvas;//画布,能够画东西
     private Bitmap mBitmap;//画布在此图片上画画
     private int mLastX;//x坐标
     private int mLastY;//y坐标
     private Bitmap background;//这个是背景图,咱们先不理
     public GuaGuaKa(Context context) {
         super(context);
     }
    
     public GuaGuaKa(Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
         mPath = new Path();
    
     }
    
     public GuaGuaKa(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
     }
    
     public GuaGuaKa(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
     }
  2. 复写onMeasure方法htm

    咱们首先得到View的宽高,而后以此的宽高建立一个画布,同时,对画笔进行一些设置对象

    @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         Log.d(TAG, "onMeasure: 测量");
         int width = getMeasuredWidth();
         int height = getMeasuredHeight();
         // 初始化bitmap
         mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);//以得到的宽高建立一个32位的bitmap
         mCanvas = new Canvas(mBitmap);//以bitmap建立了一个画布
         mCanvas.drawColor(Color.GREEN);//设置画布的颜色为绿色
         //背景图,下一节解析此部分代码,先注释掉
         /*BitmapDrawable bitmap = (BitmapDrawable) getResources().getDrawable(R.drawable.rewrite6);
         background = bitmap.getBitmap();
         background = Bitmap.createScaledBitmap(background,width,height,true);*/
         // 设置画笔
         mOutterPaint.setColor(Color.BLUE);
         mOutterPaint.setAntiAlias(true);//使用抗锯齿功能,会消耗较大资源,绘制图形速度会变慢
         mOutterPaint.setDither(true);//图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰
         mOutterPaint.setStyle(Paint.Style.STROKE);
         mOutterPaint.setStrokeJoin(Paint.Join.ROUND);//圆角,平滑
         mOutterPaint.setStrokeCap(Paint.Cap.ROUND); //圆角
         mOutterPaint.setStrokeWidth(20); // 设置画笔宽度
     }
  3. 复写onTouchEvent方法blog

    咱们在这里复写,处理一下用户的触摸事件当手指按到屏幕上的时候,Path路径之中就使用moveto方法,移动到手指当前位置,
    invalidate刷新View,回调onDraw方法,(尚未画出来)。以后,手指移动,action处因而处于ACTION_MOVE的状态,Path路径使用lineto方法(画直线),同时,将x,y坐标进行了更新,invalidate刷新View,回调onDraw方法,canvas经过drawpath使用画笔将path画了出来,以后若是用户没有抬起手指,则继续循环ACTION_MOVE中的步骤继承

    @Override
     public boolean onTouchEvent(MotionEvent event) {
         //当手指按到屏幕上的时候,Path路径之中就使用moveto方法,移动到手指当前位置,invalidate刷新View,回调onDraw方法,(尚未画出来),canvas就将画笔移动到那个坐标
         //以后,手指移动,action是处于ACTION_MOVE的状态,Path路径使用lineto方法(画直线),
         // 同时,将x,y坐标进行了更新,invalidate刷新View,回调onDraw方法,canvas经过drawpath使用画笔将path画了条出来(画直线),以后若是用户没有抬起手指,则继续循环ACTION_MOVE中的步骤
    
         int action = event.getAction();
         int x = (int) event.getX();//得到x坐标
         int y = (int) event.getY();//得到y坐标
         switch (action){
             case MotionEvent.ACTION_DOWN:
                 mLastX = x; 
                 mLastY = y; 
                 mPath.moveTo(mLastX, mLastY);//以后回调onDraw方法canvas将path
                 break;
             case MotionEvent.ACTION_MOVE:
                 mPath.lineTo(x, y);//以后回调onDraw方法时canvas画直线到(x,y)该点
                 mLastX = x;//更新x坐标
                 mLastY = y;//更新y坐标
                 break;
             default:break;
         }
         invalidate();//刷新View,回调onDraw方法
         Log.d(TAG, "onTouchEvent: invalidate");
         return true;
    }
  4. 复写onDraw方法教程

    以后咱们复写onDraw方法,在这里canvas用画笔开始画画

    @Override
     protected void onDraw(Canvas canvas) {
         Log.d(TAG, "onDraw: 画");
         //canvas.drawBitmap(background,0,0,null);//下一节解析,这里先注释掉
         //mOutterPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));//下一节解析,注释掉
         mCanvas.drawPath(mPath, mOutterPaint);//mCanvas是咱们定义的画布,用户的每次的手指轨迹都被path记录下来,以后mcanvas就使用画笔将用户的手指轨迹画了出来
         canvas.drawBitmap(mBitmap, 0,0, null);//将mBitmap画出来
     }

PS:这里测试的时候发现mCanvas与canvas的顺序能够换个位置,影响不大
测试动态图

简单的流程图

流程图

补充 双缓冲技术

事实上,刮刮卡这个项目用到了双缓冲技术

双缓冲即在内存中建立一个与屏幕绘图区域一致的对象,先将图形绘制到内存中的这个对象上,再一次性将这个对象上的图形拷贝到屏幕上,这样能大大加快绘图的速度。

咱们定义了一个mBitmap,以后使用这个MBitmap创建了一个画布,实际上咱们的mCanvas只在mBitmap上画画

mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);//以得到的宽高建立一个32位的bitmap
    mCanvas = new Canvas(mBitmap);//以bitmap建立了一个画布
    mCanvas.drawColor(Color.GREEN);

mCanvas负责将用户的手指痕迹经过drawpath方法画出来

mCanvas.drawPath(mPath, mOutterPaint);

以后,onDraw方法里面的canvas则将MBitmap复制并显示出来

canvas.drawBitmap(mBitmap, 0,0, null);//将mBitmap画出来(将MBitmap直接复制到View上显示)
相关文章
相关标签/搜索