Android自定义控件(一)——抽奖刮刮乐的实现

2024-02-18 22:20

本文主要是介绍Android自定义控件(一)——抽奖刮刮乐的实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

飞来千丈玉蜈蚣,横驾三天白螮蝀,凿开万窍黄云洞。看星低落镜中,月华明秋影玲珑。赑屭金环重,狻猊石柱雄,铁锁囚龙。

今天小编专门准备开一个Android自定义控件栏目,来分析Android常用的各种自定义控件知识,而今天的开篇,就从Android的自定义控件刮刮乐讲起把,为了让大家感兴趣,第一篇就不赘述理论,直接来玩一个有趣的刮刮乐控件。

众所周知,手机APP中有许多的抽奖方式,比如转盘抽奖,翻牌抽奖等,而今天我们只将刮刮乐抽奖,因为这个在手机APP之中用的还是挺多了,相信以后基本都能用的到。

1.创建自定义View

说到自定义控件当然就需要自定义View来实现刮刮乐,所以选择首先就需要在Android Studio中创建View,实现View常用的三个构造函数,代码如下图所示:

public class ShaveView extends View {public ShaveView(Context context) {super(context);}public ShaveView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);}public ShaveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}
}

其中第二个View构造函数,是我们最常用的,也就是将控件直接写在Layout.xml之中,就会调用此方法,所以我们的初始化工作会在这里进行,不过我们第一步还是要定义成员变量,下面就是用的的成员变量代码:

private float mPreX,mPreY;//刮刮乐手指定位的X,Y坐标
private Bitmap dstBitmap,srcBitmap;//目标图像(手指刮除图层(白色图层)),原图像也就是刮除的灰色图层
private Paint mPaint,mTextPaint;//图像画笔工具,文字画笔工具
private Path mPath;//手指刮除路径
private int strLength;//文字的长度
private int strHeight;//文字的高度
private String textStr="恭喜你中奖了";//刮除后显示的文字

2.初始化控件参数

作为自定义View来说,有一个值得关注的参数,那就是硬件加速,但是有的绘图函数并不支持硬件加速,比如今天小编讲的PorterDuffXfermode,他的部分函数并不支持硬件加速,如果你不知道哪些函数不支持硬件加速,最好关掉硬件加速设置:

setLayerType(LAYER_TYPE_SOFTWARE,null);

接着,我们初始化成员变量,避免后面调用的时候为空,造成空指针错误,代码如下:

this.mPaint=new Paint();
this.mPaint.setColor(Color.RED);//刮刮乐擦除线条颜色
this.mPaint.setStrokeWidth(45);//刮刮乐擦除线宽度
this.mPaint.setStyle(Paint.Style.STROKE);//设置为描边
this.mPath=new Path();
this.mTextPaint=new Paint();
this.mTextPaint.setColor(Color.BLACK);//设置字体颜色
this.mTextPaint.setTextSize(56);//设置字体大小
Rect rect = new Rect();
this.mTextPaint.getTextBounds(textStr,0,textStr.length(),rect);//获取文字的宽高,存储在rect中
this.strLength=rect.width();//获取文字的宽
this.strHeight=rect.height();//获取文字的高

3.onTouchEvent(MotionEvent event)实现

我们是在写一个刮刮乐控件,所以需要捕捉手势操作,而自定义View中的onTouchEvent()就是专门拦截用户手势的,这里我们利用贝济埃曲线将手势连接起来,形成手势轨迹,代码如下:

@Override
public boolean onTouchEvent(MotionEvent event) {switch (event.getAction()){case MotionEvent.ACTION_DOWN:mPath.moveTo(event.getX(),event.getY());//贝济埃曲线起点this.mPreX=event.getX();this.mPreY=event.getY();return true;case MotionEvent.ACTION_MOVE:float endX=(this.mPreX+event.getX())/2;float endY=(this.mPreY+event.getY())/2;mPath.quadTo(this.mPreX,this.mPreY,endX,endY);//画贝济埃曲线this.mPreX=event.getX();this.mPreY=event.getY();break;default:break;}postInvalidate();return super.onTouchEvent(event);
}

肯定有人会问什么是贝济埃曲线,这个后续也会将,这里你只需要知道,贝济埃曲线将手指两点之间的线条变得更平滑一些就行。这里代码的意思是,手指记录按下点,然后捕捉移动手指位置,计算得出贝济埃曲线的终点与起始点。

4.OnDraw(Canvas canvas)实现

接着就是画出原图层与目标图层呢?有过PS基础的应该都知道,PS中有一个混合模式,而今天介绍的PorterDuffXfermode也是混合模式,其中有18中混合模式,今天要使用的是PorterDuff.Mode.SRC_OUT混合模式,也就是当目标图层不透明时,计算结果将是透明的,简单的理解就是刮刮乐刮除的区域透明(灰色目标图层与手指刮除图层相交位置透明),也就显示了刮刮乐后面的文字。

理解了混合模式后,我们再来看看onDraw()前面代码:

canvas.drawColor(Color.RED);//设置自定义View背景为白色
if(this.dstBitmap==null || this.srcBitmap==null){//初始化目标图层与源图层
this.srcBitmap=Bitmap.createBitmap(getWidth()/4*3,getHeight()/4*3,Bitmap.Config.ARGB_8888);//源图层,也就是刮刮乐灰色图层
this.dstBitmap=Bitmap.createBitmap(getWidth(),getHeight(),Bitmap.Config.ARGB_8888);//目标图层
this.srcBitmap.eraseColor(Color.GRAY);//设置源图层背景为灰色
}
canvas.drawText(textStr,getWidth()/2-strLength/2,getHeight()/2-strHeight/2,mTextPaint);//画文字

这里我们创建好了两个图层,也可以说是两个图片,比如srcBitmap源图层背景为灰色,同时直接将文字绘制到自定义View的中间位置,而文字的X,Y坐标如下图所示:

接着就是刮刮乐最核心的代码啦,所以需要认真仔细的看下,代码如下:

int layerId=canvas.saveLayer(0,0,getWidth(),getHeight(),null,Canvas.ALL_SAVE_FLAG);
Canvas c=new Canvas(dstBitmap);//目标图层
c.drawPath(mPath,mPaint);//绘制手指路径canvas.drawBitmap(dstBitmap,0,0,mPaint);//先画目标图层
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));//设置混合模式
canvas.drawBitmap(srcBitmap,getWidth()/8,getHeight()/8,mPaint);//在画源图层this.mPaint.setXfermode(null);//设置混合模式为空
canvas.restoreToCount(layerId);

这里我们使用离屏绘制,什么是离屏绘制,后续小编会讲,你现在只需要知道离屏绘制的代码在canvas.save与canvas.restoreToCount中间即可。

其中mPath记录的是手指刮除的位置轨迹,把它先画到dstBitmap目标图层上,然后,根据Xfermode的混合模式,先后画出目标图层与源图层,记住,这个顺序不能变,这个是刮刮乐代码中最核心的代码。

可能有的小伙伴注意到了,这里小编源图层右上角的坐标为(getWidth()/8,getHeight()/8),这是因为我们使用中,大多数刮刮乐背景边缘并不是灰色,灰色图层在中间显示,所以这里小编将源图层移动到了整个画布的相对中间点的位置,这个可以随意调节,使得看起来更加美观。

Github代码下载地址:点击下载

 

这篇关于Android自定义控件(一)——抽奖刮刮乐的实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/722633

相关文章

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、