用Canvas绘制一个数字键盘

简介: 用Canvas轻轻松松搞一个数字键盘,本身没什么难度,这种效果实现的方式也是多种多样,这篇只是其中的一种,要说本篇有什么特别之处,可能就是纯绘制,没有用到其它的任何资源,一个类就搞定了。

Hello啊老铁们,这篇文章还是阐述自定义View相关的内容,用Canvas轻轻松松搞一个数字键盘,本身没什么难度,这种效果实现的方式也是多种多样,这篇只是其中的一种,要说本篇有什么特别之处,可能就是纯绘制,没有用到其它的任何资源,一个类就搞定了,文中不足之处,各位老铁多包含,多指正。


本篇的内容大概如下:


1、效果展示

2、快速使用及属性介绍

3、具体代码实现

4、源文件地址及总结


一、效果展示


很常见的数字键盘,背景,颜色,文字大小,点击的事件等等,均已配置好,大家可以看第2项中相关介绍。


静态效果展示:



动态效果展示,录了一个gif,大家可以看下具体的触摸效果。



二、快速使用及属性介绍


鉴于本身就一个类,不值当去打一个远程的Maven,大家用的话可以直接下载,把文件复制到项目里即可,复制到项目中,就可以按照下面的步骤去使用。


引用


1、xml中引用,可以根据需要,设置宽高及相关属性


<KeyboardViewandroid:id="@+id/key_board_view"android:layout_width="match_parent"android:layout_height="wrap_content"/>


2、代码直接创建,然后追加到相关视图里即可


valkeyboardView=KeyboardView(this)


方法及属性介绍


单个点击的触发监听:


keyboardView.setOnSingleClickListener {
//键盘点击的数字}


获取最终的字符串点击监听,其实就是把你点击的数字拼接起来,一起输出,特别在密码使用的时候,省的你再自己拼接了,配合number_size属性和setNumberSize方法一起使用,默认是6个长度,可以根据需求,动态设置。


keyboardView.setOnNumClickListener {
//获取最终的点击数字字符串,如:123456,通过number_size属性或setNumberSize方法,设置最长字符    }


其它方法

方法

参数

概述

hintLetter

无参

隐藏字母

setBackGroundColor

int类型的颜色值

设置整体背景色

setRectBackGroundColor

int类型的颜色值

设置数字格子背景色

setTextColor

int类型的颜色值

设置文字颜色

setTextSize

Float

设置数字大小

setNumberSize

int类型

设置按下的数字总长度

setRectHeight

Float

设置数字键盘每格高度

setSpacing

Float

设置数字键盘每格间隔距离


属性介绍


属性

类型

概述

background_color

color

背景颜色

rect_background_color

color

数字格子背景色

down_background_color

color

手指按下的背景颜色

text_color

color

文字颜色

text_size

dimension

文字大小

letter_text_size

dimension

字母的文字大小

rect_height

dimension

数字格子高度

rect_spacing

dimension

格子间距

is_rect_letter

boolean

是否显示字母

number_size

integer

按下的数字总长度字符


三、具体代码实现


代码实现上其实也没有什么难的,主要就是用到了自定义View中的onDraw方法,简单的初始化,设置画笔,默认属性就不一一介绍了,直接讲述主要的绘制部分,我的实现思路如下,第一步,绘制方格,按照UI效果图,应该是12个方格,简图如下,需要注意的是,第10个是空的,也就是再绘制的时候,需要进行跳过,最后一个是一个删除的按钮,绘制的时候也需要跳过,直接绘制删除按钮即可。


1、关于方格的绘制


方格的宽度计算很简单,(手机的宽度-方格间距*4)/3即可,绘制方格,直接调用canvas的drawRoundRect方法,单纯的和数字一起绘制,直接遍历12个数即可,记住9的位置跳过,11的位置,绘制删除按钮。


mRectWidth= (width-mSpacing*4) /3mPaint!!.strokeWidth=10ffor (iin0..11) {
//设置方格valrect=RectF()
valiTemp=i/3valrectTop=mHeight*iTemp+mSpacing* (iTemp+1f)
rect.top=rectToprect.bottom=rect.top+mHeightvarleftSpacing= (mSpacing* (i%3f))
leftSpacing+=mSpacingrect.left=mRectWidth!!* (i%3f) +leftSpacingrect.right=rect.left+mRectWidth!!//9的位置是空的,跳过不绘制if (i==9) {
continue            }
//11的位置,是删除按钮,直接绘制删除按钮if (i==11) {
drawDelete(canvas, rect.right, rect.top)
continue            }
mPaint!!.textSize=mTextSizemPaint!!.style=Paint.Style.FILL//按下的索引 和 方格的 索引一致,改变背景颜色if (mDownPosition== (i+1)) {
mPaint!!.color=mDownBackGroundColor            } else {
mPaint!!.color=mRectBackGroundColor            }
//绘制方格canvas!!.drawRoundRect(rect, 10f, 10f, mPaint!!)
}


2、关于数字的绘制


没有字母显示的情况下,数字要绘制到中间的位置,有字母的情况下,数字应该往上偏移,让整体进行居中,通过方格的宽高和自身文字内容的宽高来计算显示的位置。


//绘制数字mPaint!!.color=mTextColorvarkeyWord="${i + 1}"//索引等于 10 从新赋值为 0if (i==10) {
keyWord="0"            }
valrectWord=Rect()
mPaint!!.getTextBounds(keyWord, 0, keyWord.length, rectWord)
valwWord=rectWord.width()
valhtWord=rectWord.height()
varyWord=rect.bottom-mHeight/2+ (htWord/2)
//上移if (i!=0&&i!=10&&mIsShowLetter) {
yWord-=htWord/3            }
canvas.drawText(
keyWord,
rect.right-mRectWidth!!/2- (wWord/2),
yWord,
mPaint!!            )


3、关于字母的绘制


因为字母是和数字一起绘制的,所以需要对应的字母则向下偏移,否则不会达到整体居中的效果,具体的绘制如下,和数字的绘制类似,拿到方格的宽高,以及字母的宽高,进行计算横向和纵向位置。


//绘制字母if ((iin1..8) &&mIsShowLetter) {
mPaint!!.textSize=mLetterTextSizevals=mWordArray[i-1]
valrectW=Rect()
mPaint!!.getTextBounds(s, 0, s.length, rectW)
valw=rectW.width()
valh=rectW.height()
canvas.drawText(
s,
rect.right-mRectWidth!!/2- (w/2),
rect.bottom-mHeight/2+h*2,
mPaint!!                )
            }

 

4、关于删除按钮的绘制


删除按钮是纯线条的绘制,没有使用图片资源,不过大家可以使用图片资源,因为图片资源还是比较的靠谱。


/*** AUTHOR:AbnerMing* INTRODUCE:绘制删除按键,直接canvas自绘,不使用图片*/privatefundrawDelete(canvas: Canvas?, right: Float, top: Float) {
valrWidth=15vallineWidth=35valx=right-mRectWidth!!/2- (rWidth+lineWidth) /4valy=top+mHeight/2valpath=Path()
path.moveTo(x-rWidth, y)
path.lineTo(x, y-rWidth)
path.lineTo(x+lineWidth, y-rWidth)
path.lineTo(x+lineWidth, y+rWidth)
path.lineTo(x, y+rWidth)
path.lineTo(x-rWidth, y)
path.close()
mPaint!!.strokeWidth=2fmPaint!!.style=Paint.Style.STROKEmPaint!!.color=mTextColorcanvas!!.drawPath(path, mPaint!!)
//绘制小×号mPaint!!.style=Paint.Style.FILLmPaint!!.textSize=30fvalcontent="×"valrectWord=Rect()
mPaint!!.getTextBounds(content, 0, content.length, rectWord)
valwWord=rectWord.width()
valhtWord=rectWord.height()
canvas.drawText(
content,
right-mRectWidth!!/2-wWord/2+3,
y+htWord/3*2+2,
mPaint!!        )
    }


5、按下效果的处理


按下的效果处理,重写onTouchEvent方法,然后在down事件里通过,手指触摸的XY坐标,判断当前触摸的是那个方格,记录下索引,并使用invalidate进行刷新View,在onDraw里进行改变画笔的颜色即可。


根据XY坐标,返回触摸的位置


/*** AUTHOR:AbnerMing* INTRODUCE:返回触摸的位置*/privatefungetTouch(upX: Float, upY: Float): Int {
varposition=-2for (iin0..11) {
valiTemp=i/3valrectTop=mHeight*iTemp+mSpacing* (iTemp+1f)
valtop=rectTopvalbottom=top+mHeightvarleftSpacing= (mSpacing* (i%3f))
leftSpacing+=10fvalleft=mRectWidth!!* (i%3f) +leftSpacingvalright=left+mRectWidth!!if (upX>left&&upX<right&&upY>top&&upY<bottom) {
position=i+1//位置11默认为 数字  0if (position==11) {
position=0                }
//位置12  数字为 -1 意为删除if (position==12) {
position=-1                }
            }
        }
returnposition    }

 

在onDraw里进行改变画笔的颜色。


//按下的索引 和 方格的 索引一致,改变背景颜色if (mDownPosition== (i+1)) {
mPaint!!.color=mDownBackGroundColor            } else {
mPaint!!.color=mRectBackGroundColor            }


6、wrap_content处理


在使用当前控件的时候,需要处理wrap_content的属性,否则效果就会和match_parent一样了,具体的处理如下,重写onMeasure方法,获取高度的模式后进行单独的设置。


overridefunonMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
valheightSpecMode=MeasureSpec.getMode(heightMeasureSpec)
valwidthSpecSize=MeasureSpec.getSize(widthMeasureSpec)
if (heightSpecMode==MeasureSpec.AT_MOST) {
//当高度为 wrap_content 时 设置一个合适的高度setMeasuredDimension(widthSpecSize, (mHeight*4+mSpacing*5+10).toInt())
        }
    }


四、源文件地址及总结


源文件地址:

https://github.com/AbnerMing888/KeyboardView


源文件不是一个项目,是一个单纯的文件,大家直接复制到项目中使用即可,对于26个英文字母键盘绘制,基本上思路是一致的,大家可以在此基础上进行拓展,本文就先到这里吧,整体略有瑕疵,忘包含。

相关文章
|
3月前
|
前端开发
|
4月前
|
前端开发
canvas详解04-绘制文字
canvas详解04-绘制文字
31 2
canvas详解04-绘制文字
|
4月前
|
缓存 前端开发 JavaScript
canvas详解01-绘制基本图形
canvas详解01-绘制基本图形
50 2
|
8月前
|
移动开发 前端开发 JavaScript
使用Canvas绘制图形和动画
使用Canvas绘制图形和动画
130 0
|
前端开发 算法 JavaScript
使用 canvas 拖拽绘制矩形(带撤销)
之前预览网络摄像头的需求又有了下文,要在视频预览之上进行拖拽生成矩形边框,用于后台算法对区域内容进行一些处理。
240 0
|
前端开发
canvas绘制五角星
canvas绘制五角星
147 0
|
前端开发
基于canvas绘制边框环绕进度条
基于canvas绘制边框环绕进度条
193 0
基于canvas绘制边框环绕进度条
|
前端开发
Canvas绘制圆形头像
Canvas绘制圆形头像
197 0
Canvas绘制圆形头像
|
Web App开发 移动开发 前端开发
H5:画布Canvas基础知识讲解(三)之文字、阴影、颜色渐变
​上一节介绍了H5:画布Canvas基础知识讲解(二)之插入图像、像素级操作,接下来继续讲解H5:画布Canvas基础。
|
前端开发
用canvas绘制一个烟花动画
前言 在我们日常开发中贝塞尔曲线无处不在: svg 中的曲线(支持 2阶、 3阶) canvas 中绘制贝塞尔曲线 几乎所有前端2D或3D图形图表库(echarts,d3,three.js)都会使用到贝塞尔曲线 所以掌握贝塞尔曲线势在必得。这篇文章主要是实战篇,不会介绍和贝塞尔相关的知识, 如果有同学对贝塞尔曲线不是很清楚的话:可以查看我这篇文章——深入理解SVG 绘制贝塞尔曲线 第一步我们先创建ctx, 用ctx 画一个二阶贝塞尔曲线看下。二阶贝塞尔曲线有1个控制点,一个起点,一个终点。 const canvas = document.getElementById( 'canvas'
用canvas绘制一个烟花动画