本文正在参加「金石方案 . 分割6万现金大奖」

Hello啊老铁们,这篇文章仍是论述自定义View相关的内容,用Canvas轻轻松松搞一个数字键盘,自身没什么难度,这种作用完成的办法也是多种多样,这篇只是其中的一种,要说本篇有什么特别之处,可能便是纯制作,没有用到其它的任何资源,一个类就搞定了,文中不足之处,各位老铁多包括,多纠正。

今日的内容大概如下:

1、作用展现

2、快速运用及特点介绍

3、详细代码完成

4、源文件地址及总结

一、作用展现

很常见的数字键盘,布景,色彩,文字大小,点击的事情等等,均已配置好,我们能够看第2项中相关介绍。

静态作用展现:

用Canvas绘制一个数字键盘

动态作用展现,录了一个gif,我们能够看下详细的接触作用。

用Canvas绘制一个数字键盘

二、快速运用及特点介绍

鉴于自身就一个类,不值当去打一个远程的Maven,我们用的话能够直接下载,把文件复制到项目里即可,复制到项目中,就能够依照下面的步骤去运用。

引用

1、xml中引用,能够依据需求,设置宽高及相关特点

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

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

val keyboardView=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个是空的,也便是再制作的时分,需求进行越过,最终一个是一个删去的按钮,制作的时分也需求越过,直接制作删去按钮即可。

用Canvas绘制一个数字键盘

1、关于方格的制作

方格的宽度核算很简略,(手机的宽度-方格间距*4)/3即可,制作方格,直接调用canvas的drawRoundRect办法,单纯的和数字一同制作,直接遍历12个数即可,记住9的方位越过,11的方位,制作删去按钮。

mRectWidth = (width - mSpacing * 4) / 3
mPaint!!.strokeWidth = 10f
for (i in 0..11) {
            //设置方格
            val rect = RectF()
            val iTemp = i / 3
            val rectTop = mHeight * iTemp + mSpacing * (iTemp + 1f)
            rect.top = rectTop
            rect.bottom = rect.top + mHeight
            var leftSpacing = (mSpacing * (i % 3f))
            leftSpacing += mSpacing
            rect.left = mRectWidth!! * (i % 3f) + leftSpacing
            rect.right = rect.left + mRectWidth!!
            //9的方位是空的,越过不制作
            if (i == 9) {
                continue
            }
            //11的方位,是删去按钮,直接制作删去按钮
            if (i == 11) {
                drawDelete(canvas, rect.right, rect.top)
                continue
            }
            mPaint!!.textSize = mTextSize
            mPaint!!.style = Paint.Style.FILL
            //按下的索引 和 方格的 索引一致,改动布景色彩
            if (mDownPosition == (i + 1)) {
                mPaint!!.color = mDownBackGroundColor
            } else {
                mPaint!!.color = mRectBackGroundColor
            }
            //制作方格
            canvas!!.drawRoundRect(rect, 10f, 10f, mPaint!!)
}

2、关于数字的制作

没有字母显现的情况下,数字要制作到中间的方位,有字母的情况下,数字应该往上偏移,让全体进行居中,经过方格的宽高和自身文字内容的宽高来核算显现的方位。

//制作数字
            mPaint!!.color = mTextColor
            var keyWord = "${i + 1}"
            //索引等于 10 重新赋值为 0
            if (i == 10) {
                keyWord = "0"
            }
            val rectWord = Rect()
            mPaint!!.getTextBounds(keyWord, 0, keyWord.length, rectWord)
            val wWord = rectWord.width()
            val htWord = rectWord.height()
            var yWord = 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 ((i in 1..8) && mIsShowLetter) {
                mPaint!!.textSize = mLetterTextSize
                val s = mWordArray[i - 1]
                val rectW = Rect()
                mPaint!!.getTextBounds(s, 0, s.length, rectW)
                val w = rectW.width()
                val h = rectW.height()
                canvas.drawText(
                    s,
                    rect.right - mRectWidth!! / 2 - (w / 2),
                    rect.bottom - mHeight / 2 + h * 2,
                    mPaint!!
                )
            }

4、关于删去按钮的制作

删去按钮是纯线条的制作,没有运用图片资源,不过我们能够运用图片资源,由于图片资源仍是比较的靠谱。

 /**
     * AUTHOR:AbnerMing
     * INTRODUCE:制作删去按键,直接canvas自绘,不运用图片
     */
    private fun drawDelete(canvas: Canvas?, right: Float, top: Float) {
        val rWidth = 15
        val lineWidth = 35
        val x = right - mRectWidth!! / 2 - (rWidth + lineWidth) / 4
        val y = top + mHeight / 2
        val path = 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 = 2f
        mPaint!!.style = Paint.Style.STROKE
        mPaint!!.color = mTextColor
        canvas!!.drawPath(path, mPaint!!)
        //制作小号
        mPaint!!.style = Paint.Style.FILL
        mPaint!!.textSize = 30f
        val content = ""
        val rectWord = Rect()
        mPaint!!.getTextBounds(content, 0, content.length, rectWord)
        val wWord = rectWord.width()
        val htWord = 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:返回接触的方位
     */
    private fun getTouch(upX: Float, upY: Float): Int {
        var position = -2
        for (i in 0..11) {
            val iTemp = i / 3
            val rectTop = mHeight * iTemp + mSpacing * (iTemp + 1f)
            val top = rectTop
            val bottom = top + mHeight
            var leftSpacing = (mSpacing * (i % 3f))
            leftSpacing += 10f
            val left = mRectWidth!! * (i % 3f) + leftSpacing
            val right = left + mRectWidth!!
            if (upX > left && upX < right && upY > top && upY < bottom) {
                position = i + 1
                //方位11默许为 数字  0
                if (position == 11) {
                    position = 0
                }
                //方位12  数字为 -1 意为删去
                if (position == 12) {
                    position = -1
                }
            }
        }
        return position
    }

在onDraw里进行改动画笔的色彩。

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

6、wrap_content处理

在运用当时控件的时分,需求处理wrap_content的特点,不然作用就会和match_parent相同了,详细的处理如下,重写onMeasure办法,获取高度的模式后进行单独的设置。

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

四、源文件地址及总结

源文件地址:

github.com/AbnerMing88…

源文件不是一个项目,是一个单纯的文件,我们直接复制到项目中运用即可,关于26个英文字母键盘制作,基本上思路是一致的,我们能够在此基础上进行拓宽,本文就先到这里吧,全体略有瑕疵,忘包括。