Android项目刮刮奖详解(一)
前言
最近正在学鸿洋大大的刮刮奖,感觉学有所得,便是来写篇详解(尽管网上有很多了,不过毕竟是自己写的,自己以后方便复习),正文开始
目标
实现画板功能
思路
我们需要自定义View来实现画板功能,之后再将其稍微改造即可。
关于自定义View,如果没有了解的同学建议先去了解一下,百度自定义View就会有许多相关教程了,
我在这里也就简单的提一下,自定义View常用的三大类,Paint(画笔),Path(路径),
Canvas(画布),三大类方法介绍
继承View,实现构造方法
四个构造方法,我们主要实现两个参数的构造方法即可
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);
}
复写onMeasure方法
我们首先获得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); // 设置画笔宽度
}
复写onTouchEvent方法
我们在这里复写,处理一下用户的触摸事件当手指按到屏幕上的时候,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;
}
复写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上显示)
Android项目刮刮奖详解(一)的更多相关文章
- Android项目刮刮奖详解(二)
Android项目刮刮奖详解(一) 前言 上期我们简单地实现了一个画板的功能,用户可以在上面乱写乱画,其实,刮刮奖也是如此,用户刮奖的时候也是乱写乱画的. 刮刮奖原理 一共有两层画布,底层画布存放中奖 ...
- Android项目刮刮奖详解(三)
Android项目刮刮奖详解(二) 前言 上一期我们已经实现了一个简易的刮刮卡功能,这一期我们来将其完善一下 目标 将刮刮奖的宽高改为合适高度 将刮刮奖位置居中 将信息层的图片换成文字(重点) 实现 ...
- Android项目刮刮奖详解(四)
Android项目刮刮奖详解(三) 前言 上一期我们已经是完成了刮刮卡的基本功能,本期就是给我们的项目增加个功能以及美化一番 目标 增加功能 用户刮卡刮到一定程度的时候,清除遮盖层 在遮盖层放张图片, ...
- Android项目刮刮奖详解扩展篇——开源刮刮奖View的制作
Android项目刮刮奖详解(四) 前言 我们已经成功实现了刮刮奖的功能了,本期是扩展篇,我们把这个View直接定义成开源控件,发布到JitPack上,以后有需要也可以直接使用,关于自定义控件的知识, ...
- Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
- Android Gradle manifestPlaceholders 占位符详解
Android Gradle manifestPlaceholders 占位符详解 在实际项目中,AndroidManifest里十几个地方的值是需要动态的改变(生成apk文件的时候).如果每次去改也 ...
- Android高效率编码-第三方SDK详解系列(三)——JPush推送牵扯出来的江湖恩怨,XMPP实现推送,自定义客户端推送
Android高效率编码-第三方SDK详解系列(三)--JPush推送牵扯出来的江湖恩怨,XMPP实现推送,自定义客户端推送 很久没有更新第三方SDK这个系列了,所以更新一下这几天工作中使用到的推送, ...
- 【Android 应用开发】Ubuntu 下 Android Studio 开发工具使用详解 (旧版本 | 仅作参考)
. 基本上可以导入项目开始使用了 ... . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21035637 ...
- Android高效率编码-第三方SDK详解系列(二)——Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能
Android高效率编码-第三方SDK详解系列(二)--Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能 我的本意是第二篇写Mob的shareSD ...
- Android高效率编码-第三方SDK详解系列(一)——百度地图,绘制,覆盖物,导航,定位,细腻分解!
Android高效率编码-第三方SDK详解系列(一)--百度地图,绘制,覆盖物,导航,定位,细腻分解! 这是一个系列,但是我也不确定具体会更新多少期,最近很忙,主要还是效率的问题,所以一些有效的东西还 ...
随机推荐
- 快速搭建react项目骨架(按需加载、redux、axios、项目级目录等等)
一.前言 最近整理了一下项目骨架,顺便自定义了一个脚手架,方便日后使用.我会从头开始,步骤一步步写明白,如果还有不清楚的可以评论区留言.先大致介绍一下这个骨架,我们采用 create-react-ap ...
- python枚举类型
笔记: 一:枚举类型的定义二:枚举类和普通类的区别 1:值不可变 2:具有防止相同标签得功能,不同标签的值可以相同! 三:枚举类型.枚举值.枚举名称 1:VIP.YELLOW.Value 获得标签的值 ...
- python语法_装饰器
装饰器的知识点储备: 1 作用域 2 高阶函数 3 闭包 内部函数,对外部作用作用域的变量进行了引用,该内部函数就认为是闭包, def outer(): x=10 def inner(): print ...
- UEditor之实现配置简单的图片上传示例
UEditor之实现配置简单的图片上传示例 原创 2016年06月11日 18:27:31 开心一笑 下班后,阿华到楼下小超市买毛巾,刚买完出来,就遇到同一办公楼里另一家公司的阿菲,之前与她远远的有过 ...
- MyEclipse最新版-版本更新说明及下载 - MyEclipse官方中文网
http://www.myeclipsecn.com/learningcenter/myeclipse-update/ [重要更新]MyEclipse 2015正式版发布 [重要更新]MyEclips ...
- 如何在Linux下查看版本信息
Linux下如何查看版本信息, 包括位数.版本信息以及CPU内核信息.CPU具体型号等等,整个CPU信息一目了然. 1.# uname -a (Linux查看版本当前操作系统内核信息) L ...
- 原生JS实现下拉刷新
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8& ...
- 分布式数据中间件TDDL、Amoeba、Cobar、MyCAT架构比较
框架比较 TDDL Amoeba Cobar MyCat 点评 TDDL不同于其它几款产品,并非独立的中间件,只能算作中间层,是以Jar包方式提供给应用调用.属于JDBC Shard的思想,网上也有很 ...
- Java面试题整理:这些Java程序员面试中经常遇见的题目,必须掌握才能有好结果
1.是否可以从一个static方法内部发出对非static方法的调用? 不可以.因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时 ...
- Javascript高级编程学习笔记(89)—— Canvas(6) 变换
变换 通过上下文的变化,可以对图像进行处理后再将其绘制到画布上 当我们创建上下文时,会以默认值初始化变化矩阵,在默认的变换矩阵下所有处理都按描述直接绘制. 而当我们为上下文应用变换时,会导致使用不同的 ...