android自定義view(自定義數字鍵盤)

welchang發表於2021-09-09
  • 序言:在上週的專案中,需要做一個密碼鎖的功能,然後密碼下面還得有鍵盤,就類似支付寶支付的時候那樣:

圖片描述

當然了,我們專案的需求簡單點,純數字的就可以了,然後上週就百度了自定義鍵盤,隨便找了一個修改修改就用到專案中去了。

多謝這位簡友:

今天自己抽空寫了一個自定義View的鍵盤控制元件,下面跟大家分享一下:

思路:

1、佈局:

(1)、宮格:我們可以將這個佈局看成是宮格佈局,然後需要計算出每個小宮格在螢幕中的位置(座標),然後再用canvas畫出相應的矩形即可。
(2)、數字:我們需要計算出每個小宮格中的中心點位置(座標),然後用canvas畫數字上去,當然,我們知道最後一個是刪除鍵,並不是數字,我們可以準備一張圖片,將圖片畫到相應的位置。

2、使用者動作:

(1)、按下:使用者每一次按下的時候就表示這一次動作的開始,所以首先要將各種標識位(自定義所需要的標識位)設定成初始狀態,然後需要記錄按下的座標,然後計算出使用者按下的座標與宮格中哪個點相對應,在記錄相應數字。最後重新整理佈局
(2)、抬起:使用者抬起的時候需要重新整理佈局,然後將按下過程中記錄下的數字或者刪除鍵資訊透過介面的形式回撥給使用者,最後恢復標識位
(3)、取消:將所有的標識位恢復成初始狀態。

好了,思路就講到這裡,我們來看看onDraw方法:

protected void onDraw(Canvas canvas) {    if (!isInit) {
        initData();
   }
   mPaint.setColor(Color.WHITE);    //畫宮格
    //第一排
    canvas.drawRoundRect(10, mHeight / 2 + 10, 10 + mRectWidth, mHeight / 2 + 10 + mRectHeight, 10, 10, mPaint);
    canvas.drawRoundRect(20 + mRectWidth, mHeight / 2 + 10, 20 + 2 * mRectWidth, mHeight / 2 + 10 + mRectHeight, 10, 10, mPaint);
    canvas.drawRoundRect(30 + 2 * mRectWidth, mHeight / 2 + 10, 30 + 3 * mRectWidth, mHeight / 2 + 10 + mRectHeight, 10, 10, mPaint);    //第二排
    canvas.drawRoundRect(10, mHeight / 2 + 20 + mRectHeight, 10 + mRectWidth, mHeight / 2 + 20 + 2 * mRectHeight, 10, 10, mPaint);
    canvas.drawRoundRect(20 + mRectWidth, mHeight / 2 + 20 + mRectHeight, 20 + 2 * mRectWidth, mHeight / 2 + 20 + 2 * mRectHeight, 10, 10, mPaint);
    canvas.drawRoundRect(30 + 2 * mRectWidth, mHeight / 2 + 20 + mRectHeight, 30 + 3 * mRectWidth, mHeight / 2 + 20 + 2 * mRectHeight, 10, 10, mPaint);    //第三排
    canvas.drawRoundRect(10, mHeight / 2 + 30 + 2 * mRectHeight, 10 + mRectWidth, mHeight / 2 + 30 + 3 * mRectHeight, 10, 10, mPaint);
    canvas.drawRoundRect(20 + mRectWidth, mHeight / 2 + 30 + 2 * mRectHeight, 20 + 2 * mRectWidth, mHeight / 2 + 30 + 3 * mRectHeight, 10, 10, mPaint);
    canvas.drawRoundRect(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(10, mHeight / 2 + 40 + 3 * mRectHeight, 10 + mRectWidth, mHeight / 2 + 40 + 4 * mRectHeight, 10, 10, mPaint);
    mPaint.setColor(Color.WHITE);
    canvas.drawRoundRect(20 + mRectWidth, mHeight / 2 + 40 + 3 * mRectHeight, 20 + 2 * mRectWidth, mHeight / 2 + 40 + 4 * mRectHeight, 10, 10, mPaint);
    mPaint.setColor(Color.GRAY);
    canvas.drawRoundRect(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 && x = mHeight / 2 + 10 && y = mHeight / 2 + 20 + mRectHeight && y = mHeight / 2 + 30 + 2 * mRectHeight && y = mHeight / 2 + 40 + 3 * mRectHeight && y = 20 + mRectWidth && x = mHeight / 2 + 10 && y = mHeight / 2 + 20 + mRectHeight && y = mHeight / 2 + 30 + 2 * mRectHeight && y = mHeight / 2 + 40 + 3 * mRectHeight && y = 30 + 2 * mRectWidth && x = mHeight / 2 + 10 && y = mHeight / 2 + 20 + mRectHeight && y = mHeight / 2 + 30 + 2 * mRectHeight && y = mHeight / 2 + 40 + 3 * mRectHeight && 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 > 0 && clickY > 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;
        }
    }

接下來再來看看效果吧:

圖片描述

現在看起來舒服多了,_

程式碼我已經上傳到,



作者:24K純帥豆
連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4830/viewspace-2803059/,如需轉載,請註明出處,否則將追究法律責任。

相關文章