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

相关文章

python+OpenCV反投影图像的实现示例详解

《python+OpenCV反投影图像的实现示例详解》:本文主要介绍python+OpenCV反投影图像的实现示例详解,本文通过实例代码图文并茂的形式给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录一、前言二、什么是反投影图像三、反投影图像的概念四、反向投影的工作原理一、利用反向投影backproj

Django之定时任务django-crontab的实现

《Django之定时任务django-crontab的实现》Django可以使用第三方库如django-crontab来实现定时任务的调度,本文主要介绍了Django之定时任务django-cront... 目录crontab安装django-crontab注册应用定时时间格式定时时间示例设置定时任务@符号

Python中edge-tts实现便捷语音合成

《Python中edge-tts实现便捷语音合成》edge-tts是一个功能强大的Python库,支持多种语言和声音选项,本文主要介绍了Python中edge-tts实现便捷语音合成,具有一定的参考价... 目录安装与环境设置文本转语音查找音色更改语音参数生成音频与字幕总结edge-tts 是一个功能强大的

Java实现按字节长度截取字符串

《Java实现按字节长度截取字符串》在Java中,由于字符串可能包含多字节字符,直接按字节长度截取可能会导致乱码或截取不准确的问题,下面我们就来看看几种按字节长度截取字符串的方法吧... 目录方法一:使用String的getBytes方法方法二:指定字符编码处理方法三:更精确的字符编码处理使用示例注意事项方

使用Python和PaddleOCR实现图文识别的代码和步骤

《使用Python和PaddleOCR实现图文识别的代码和步骤》在当今数字化时代,图文识别技术的应用越来越广泛,如文档数字化、信息提取等,PaddleOCR是百度开源的一款强大的OCR工具包,它集成了... 目录一、引言二、环境准备2.1 安装 python2.2 安装 PaddlePaddle2.3 安装

嵌入式Linux之使用设备树驱动GPIO的实现方式

《嵌入式Linux之使用设备树驱动GPIO的实现方式》:本文主要介绍嵌入式Linux之使用设备树驱动GPIO的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、设备树配置1.1 添加 pinctrl 节点1.2 添加 LED 设备节点二、编写驱动程序2.1

Android 实现一个隐私弹窗功能

《Android实现一个隐私弹窗功能》:本文主要介绍Android实现一个隐私弹窗功能,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 效果图如下:1. 设置同意、退出、点击用户协议、点击隐私协议的函数参数2. 《用户协议》、《隐私政策》设置成可点击的,且颜色要区分出来res/l

spring IOC的理解之原理和实现过程

《springIOC的理解之原理和实现过程》:本文主要介绍springIOC的理解之原理和实现过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、IoC 核心概念二、核心原理1. 容器架构2. 核心组件3. 工作流程三、关键实现机制1. Bean生命周期2.

Redis实现分布式锁全解析之从原理到实践过程

《Redis实现分布式锁全解析之从原理到实践过程》:本文主要介绍Redis实现分布式锁全解析之从原理到实践过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、背景介绍二、解决方案(一)使用 SETNX 命令(二)设置锁的过期时间(三)解决锁的误删问题(四)Re

Java根据IP地址实现归属地获取

《Java根据IP地址实现归属地获取》Ip2region是一个离线IP地址定位库和IP定位数据管理框架,这篇文章主要为大家详细介绍了Java如何使用Ip2region实现根据IP地址获取归属地,感兴趣... 目录一、使用Ip2region离线获取1、Ip2region简介2、导包3、下编程载xdb文件4、J