首页 » Andorid » 临时分类 » 正文

NumberKeyboard

NumberKeyboard

自定义键盘

> >1、布局: > (1)、宫格:我们可以将这个布局看成是宫格布局,然后需要计算出每个小宫格在屏幕中的位置(坐标),然后再用canvas画出相应的矩形即可。 (2)、数字:我们需要计算出每个小宫格中的中心点位置(坐标),然后用canvas画数字上去,当然,我们知道最后一个是删除键,并不是数字,我们可以准备一张图片,将图片画到相应的位置。 > >2、用户动作: > (1)、按下:用户每一次按下的时候就表示这一次动作的开始,所以首先要将各种标识位(自定义所需要的标识位)设置成初始状态,然后需要记录按下的坐标,然后计算出用户按下的坐标与宫格中哪个点相对应,在记录相应数字。最后刷新布局 (2)、抬起:用户抬起的时候需要刷新布局,然后将按下过程中记录下的数字或者删除键信息通过接口的形式回调给用户,最后恢复标识位 (3)、取消:将所有的标识位恢复成初始状态。

好了,思路就讲到这里,我们来看看onDraw方法:

protected void onDraw(Canvas canvas) {
    if (!isInit) {
        initData();
   }
   mPaint.setColor(Color.WHITE);
           //画宫格
           //第一排
   canvas.drawRoundRect(new RectF(10, mHeight / 2 + 10, 10 + mRectWidth, mHeight / 2 + 10 + mRectHeight), 10, 10, mPaint);
   canvas.drawRoundRect(new RectF(20 + mRectWidth, mHeight / 2 + 10, 20 + 2 * mRectWidth, mHeight / 2 + 10 + mRectHeight), 10, 10, mPaint);
   canvas.drawRoundRect(new RectF(30 + 2 * mRectWidth, mHeight / 2 + 10, 30 + 3 * mRectWidth, mHeight / 2 + 10 + mRectHeight), 10, 10, mPaint);
   //第二排
   canvas.drawRoundRect(new RectF(10, mHeight / 2 + 20 + mRectHeight, 10 + mRectWidth, mHeight / 2 + 20 + 2 * mRectHeight), 10, 10, mPaint);
   canvas.drawRoundRect(new RectF(20 + mRectWidth, mHeight / 2 + 20 + mRectHeight, 20 + 2 * mRectWidth, mHeight / 2 + 20 + 2 * mRectHeight), 10, 10, mPaint);
   canvas.drawRoundRect(new RectF(30 + 2 * mRectWidth, mHeight / 2 + 20 + mRectHeight, 30 + 3 * mRectWidth, mHeight / 2 + 20 + 2 * mRectHeight), 10, 10, mPaint);
   //第三排
   canvas.drawRoundRect(new RectF(10, mHeight / 2 + 30 + 2 * mRectHeight, 10 + mRectWidth, mHeight / 2 + 30 + 3 * mRectHeight), 10, 10, mPaint);
   canvas.drawRoundRect(new RectF(20 + mRectWidth, mHeight / 2 + 30 + 2 * mRectHeight, 20 + 2 * mRectWidth, mHeight / 2 + 30 + 3 * mRectHeight), 10, 10, mPaint);
   canvas.drawRoundRect(new RectF(30 + 2 * mRectWidth, mHeight / 2 + 30 + 2 * mRectHeight, 30 + 3 * mRectWidth, mHeight / 2 + 30 + 3 * mRectHeight), 10, 10, mPaint);
   //第四排
   mPaint.setColor(Color.GRAY);
   canvas.drawRoundRect(new RectF(10, mHeight / 2 + 40 + 3 * mRectHeight, 10 + mRectWidth, mHeight / 2 + 40 + 4 * mRectHeight), 10, 10, mPaint);
   mPaint.setColor(Color.WHITE);
   canvas.drawRoundRect(new RectF(20 + mRectWidth, mHeight / 2 + 40 + 3 * mRectHeight, 20 + 2 * mRectWidth, mHeight / 2 + 40 + 4 * mRectHeight), 10, 10, mPaint);
   mPaint.setColor(Color.GRAY);
   canvas.drawRoundRect(new RectF(30 + 2 * mRectWidth, mHeight / 2 + 40 + 3 * mRectHeight, 30 + 3 * mRectWidth, mHeight / 2 + 40 + 4 * mRectHeight), 10, 10, mPaint);

    mPaint.setColor(Color.BLACK);
    mPaint.setTextSize(60);// 设置字体大小
    mPaint.setStrokeWidth(2);
    //画数字
    //第一排
    canvas.drawText("1", xs[0], ys[0], mPaint);
    canvas.drawText("2", xs[1], ys[0], mPaint);
    canvas.drawText("3", xs[2], ys[0], mPaint);
    //第二排
    canvas.drawText("4", xs[0], ys[1], mPaint);
    canvas.drawText("5", xs[1], ys[1], mPaint);
    canvas.drawText("6", xs[2], ys[1], mPaint);
    //第三排
    canvas.drawText("7", xs[0], ys[2], mPaint);
    canvas.drawText("8", xs[1], ys[2], mPaint);
    canvas.drawText("9", xs[2], ys[2], mPaint);
    //第四排
    canvas.drawText(".", xs[0], ys[3], mPaint);
    canvas.drawText("0", xs[1], ys[3], mPaint);
    canvas.drawBitmap(mBpDelete, xs[2] - mWidthOfBp / 2 + 10, ys[3] - mHeightOfBp / 2 - 10, mPaint);
}

>##### 注:上面的坐标需要我们自己算出,耐心一点,很容易算的,你只需要搞清楚在Android中屏幕是怎样的坐标系就可以了。坐标算出来之后,我们先画宫格,然后再画数字和删除键,这里有人要问了,我可以先画数字吗,NO,因为当你画完数字之后再画宫格你会发现数字不见了,为什么呢?**被你的宫格挡住了 >__<

然后我们需要重写onTouch事件,在里面判断用户的一些行为:

switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN: //按下
               //恢复默认值
            setDefault();
            /**
             *判断按下的点在哪个宫格中
             */
            invalidate();//刷新界面
            return true;
        case MotionEvent.ACTION_UP: //弹起
            invalidate();//刷新界面
            /**
             *一次按下结束,返回点击的数字
             */
            //恢复默认
            setDefault();
            return true;
        case MotionEvent.ACTION_CANCEL:  //取消
            //恢复默认值
            setDefault();
            return true;
    }

如上面伪代码所示,我写了一个方法来判断按下的点在哪个宫格中:

private void handleDown(float x, float y) {
    if (y = 10 &amp;&amp; x = mHeight / 2 + 10 &amp;&amp; y = mHeight / 2 + 20 + mRectHeight &amp;&amp; y = mHeight / 2 + 30 + 2 * mRectHeight &amp;&amp; y = mHeight / 2 + 40 + 3 * mRectHeight &amp;&amp; y = 20 + mRectWidth &amp;&amp; x = mHeight / 2 + 10 &amp;&amp; y = mHeight / 2 + 20 + mRectHeight &amp;&amp; y = mHeight / 2 + 30 + 2 * mRectHeight &amp;&amp; y = mHeight / 2 + 40 + 3 * mRectHeight &amp;&amp; y = 30 + 2 * mRectWidth &amp;&amp; x = mHeight / 2 + 10 &amp;&amp; y = mHeight / 2 + 20 + mRectHeight &amp;&amp; y = mHeight / 2 + 30 + 2 * mRectHeight &amp;&amp; y = mHeight / 2 + 40 + 3 * mRectHeight &amp;&amp; y 注:这个方法跟你之前计算出的宫格坐标有关系,所以一定不要计算错误

至此,我们写的差不多了,然后就是要提供一个接口,对外开放,方便用的时候调用,获取到数字或者其他信息:

public interface OnNumberClickListener {
    //回调点击的数字
    public void onNumberReturn(String number);

    //删除键的回调
    public void onNumberDelete();
}

在onTouch事件中使用:

case MotionEvent.ACTION_UP: //弹起
            invalidate();//刷新界面
            //一次按下结束,返回点击的数字
            if (onNumberClickListener != null) {
                if (number != null) {
                    if (number.equals("delete")) {
                        onNumberClickListener.onNumberDelete();
                    } else {
                        onNumberClickListener.onNumberReturn(number);
                    }
                }
            }
            //恢复默认
            setDefault();
            return true;

然后我们来看一下效果怎么样吧!

功能也实现了,可是强迫症很强的我看着很不舒服,不知道你们有没有,好歹这也是一个键盘吧!按下弹起的效果都没有(没有改变按下的背景),在这里我们设置一个标志位,按下弹起刷新界面就可以了。在onTouch事件中改变该标识位的值,然后在onDraw方法中判断该标识位即可:

onTouch方法中增加:

case MotionEvent.ACTION_DOWN: //按下
    type=0;
case MotionEvent.ACTION_UP: //弹起
    type=1;

onDraw方法增加:

        if (clickX &gt; 0 &amp;&amp; clickY &gt; 0) {
        if (type == 0) {  //按下刷新
            if (number.equals("delete")) {
                mPaint.setColor(Color.WHITE);
                canvas.drawRoundRect(x1, y1, x2, y2, 10, 10, mPaint);
                canvas.drawBitmap(mBpDelete, xs[2] - mWidthOfBp / 2 + 10, ys[3] - mHeightOfBp / 2 - 10, mPaint);
            } else {
                if (number.equals(".")) {
                    mPaint.setColor(Color.WHITE);
                } else {
                    mPaint.setColor(Color.GRAY);
                }
                canvas.drawRoundRect(x1, y1, x2, y2, 10, 10, mPaint);
                mPaint.setColor(Color.BLACK);
                mPaint.setTextSize(60);// 设置字体大小
                mPaint.setStrokeWidth(2);
                canvas.drawText(number, clickX, clickY, mPaint);
            }
        } else if (type == 1) {  //抬起刷新
            if (number.equals("delete")) {
                mPaint.setColor(Color.GRAY);
                canvas.drawRoundRect(x1, y1, x2, y2, 10, 10, mPaint);
                canvas.drawBitmap(mBpDelete, xs[2] - mWidthOfBp / 2 + 10, ys[3] - mHeightOfBp / 2 - 10, mPaint);
            } else {
                if (number.equals(".")) {
                    mPaint.setColor(Color.GRAY);
                } else {
                    mPaint.setColor(Color.WHITE);
                }
                canvas.drawRoundRect(x1, y1, x2, y2, 10, 10, mPaint);
                mPaint.setColor(Color.BLACK);
                mPaint.setTextSize(60);// 设置字体大小
                mPaint.setStrokeWidth(2);
                canvas.drawText(number, clickX, clickY, mPaint);
            }
            //绘制完成后,重置
            clickX = 0;
            clickY = 0;
        }
    }

接下来再来看看效果吧:

现在看起来舒服多了,~_~

2017-10-25

修复了在5.0版本以下机器上崩溃的bug

drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint)这种方式在5.0以下的机器上会报错,
需要换成drawRoundRect(RectF rect, float rx, float ry, Paint paint)

公众号

欢迎关注我的个人公众号【IT先森养成记】,专注大前端技术分享,包含Android,Java基础,Kotlin,HTML,CSS,JS等技术;在这里你能得到的不止是技术上的提升,还有一些学习经验以及志同道合的朋友,赶快加入我们,一起学习,一起进化吧!!!

公众号:IT先森养成记

下载 (0)

发表评论