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

序言:在上周的項目中,需要做一個密碼鎖的功能,然后密碼下面還得有鍵盤,就類似支付寶支付的時候那樣:

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

多謝這位簡友:[Android] 自定義輸入支付密碼的軟鍵盤

今天自己抽空寫了一個自定義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 < mHeight / 2) {return;}if (x >= 10 && x <= 10 + mRectWidth) {   //第一列clickX = xs[0];if (y >= mHeight / 2 + 10 && y <= mHeight / 2 + 10 + mRectHeight) {  //第一排(1)clickY = ys[0];x1 = 10;y1 = mHeight / 2 + 10;x2 = 10 + mRectWidth;y2 = mHeight / 2 + 10 + mRectHeight;number = "1";} else if (y >= mHeight / 2 + 20 + mRectHeight && y <= mHeight / 2 + 20 + 2 * mRectHeight) {  //第二排(4)x1 = 10;y1 = mHeight / 2 + 20 + mRectHeight;x2 = 10 + mRectWidth;y2 = mHeight / 2 + 20 + 2 * mRectHeight;clickY = ys[1];number = "4";} else if (y >= mHeight / 2 + 30 + 2 * mRectHeight && y <= mHeight / 2 + 30 + 3 * mRectHeight) {  //第三排(7)x1 = 10;y1 = mHeight / 2 + 30 + 2 * mRectHeight;x2 = 10 + mRectWidth;y2 = mHeight / 2 + 30 + 3 * mRectHeight;clickY = ys[2];number = "7";} else if (y >= mHeight / 2 + 40 + 3 * mRectHeight && y <= mHeight / 2 + 40 + 4 * mRectHeight) { //第四排(0)x1 = 10;y1 = mHeight / 2 + 40 + 3 * mRectHeight;x2 = 10 + mRectWidth;y2 = mHeight / 2 + 40 + 4 * mRectHeight;clickY = ys[3];number = ".";}} else if (x >= 20 + mRectWidth && x <= 20 + 2 * mRectWidth) {  //第二列clickX = xs[1];if (y >= mHeight / 2 + 10 && y <= mHeight / 2 + 10 + mRectHeight) {  //第一排(2)x1 = 20 + mRectWidth;y1 = mHeight / 2 + 10;x2 = 20 + 2 * mRectWidth;y2 = mHeight / 2 + 10 + mRectHeight;clickY = ys[0];number = "2";} else if (y >= mHeight / 2 + 20 + mRectHeight && y <= mHeight / 2 + 20 + 2 * mRectHeight) {  //第二排(5)x1 = 20 + mRectWidth;y1 = mHeight / 2 + 20 + mRectHeight;x2 = 20 + 2 * mRectWidth;y2 = mHeight / 2 + 20 + 2 * mRectHeight;clickY = ys[1];number = "5";} else if (y >= mHeight / 2 + 30 + 2 * mRectHeight && y <= mHeight / 2 + 30 + 3 * mRectHeight) {  //第三排(8)x1 = 20 + mRectWidth;y1 = mHeight / 2 + 30 + 2 * mRectHeight;x2 = 20 + 2 * mRectWidth;y2 = mHeight / 2 + 30 + 3 * mRectHeight;clickY = ys[2];number = "8";} else if (y >= mHeight / 2 + 40 + 3 * mRectHeight && y <= mHeight / 2 + 40 + 4 * mRectHeight) { //第四排(0)x1 = 20 + mRectWidth;y1 = mHeight / 2 + 40 + 3 * mRectHeight;x2 = 20 + 2 * mRectWidth;y2 = mHeight / 2 + 40 + 4 * mRectHeight;clickY = ys[3];number = "0";}} else if (x >= 30 + 2 * mRectWidth && x <= 30 + 3 * mRectWidth) {   //第三列clickX = xs[2];if (y >= mHeight / 2 + 10 && y <= mHeight / 2 + 10 + mRectHeight) {  //第一排(3)x1 = 30 + 2 * mRectWidth;y1 = mHeight / 2 + 10;x2 = 30 + 3 * mRectWidth;y2 = mHeight / 2 + 10 + mRectHeight;clickY = ys[0];number = "3";} else if (y >= mHeight / 2 + 20 + mRectHeight && y <= mHeight / 2 + 20 + 2 * mRectHeight) {  //第二排(6)x1 = 30 + 2 * mRectWidth;y1 = mHeight / 2 + 20 + mRectHeight;x2 = 30 + 3 * mRectWidth;y2 = mHeight / 2 + 20 + 2 * mRectHeight;clickY = ys[1];number = "6";} else if (y >= mHeight / 2 + 30 + 2 * mRectHeight && y <= mHeight / 2 + 30 + 3 * mRectHeight) {  //第三排(9)x1 = 30 + 2 * mRectWidth;y1 = mHeight / 2 + 30 + 2 * mRectHeight;x2 = 30 + 3 * mRectWidth;y2 = mHeight / 2 + 30 + 3 * mRectHeight;clickY = ys[2];number = "9";} else if (y >= mHeight / 2 + 40 + 3 * mRectHeight && y <= mHeight / 2 + 40 + 4 * mRectHeight) { //第四排(刪除鍵)x1 = 30 + 2 * mRectWidth;y1 = mHeight / 2 + 40 + 3 * mRectHeight;x2 = 30 + 3 * mRectWidth;y2 = mHeight / 2 + 40 + 4 * mRectHeight;clickY = ys[3];number = "delete";}}
}
復制代碼

注:這個方法跟你之前計算出的宮格坐標有關系,所以一定不要計算錯誤

至此,我們寫的差不多了,然后就是要提供一個接口,對外開放,方便用的時候調用,獲取到數字或者其他信息:

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;}}
復制代碼

接下來再來看看效果吧:

現在看起來舒服多了,~_~

代碼我已經上傳到Github傳送門,歡迎大家fork,star

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/453333.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/453333.shtml
英文地址,請注明出處:http://en.pswp.cn/news/453333.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

linux環境部署ltmj,Linux系統安裝與簡單配置 圖文.docx

合肥師范學院實驗報告姓名:課程名稱&#xff1a;Linux院(系&#xff1a;計算機學院 專業/年級:實於Lin^系繚公裝與苗瑕肚卅1.占克If Jf VVVork51at>un ?- If -JpMHIWortsktKia^2.?JGJiIjxiS4CLM.lt 1H. iuFI?H?*vW ?tVirtujl Machine Wisa rdGimm Oprraimv加薊aBMkonA …

矩陣的壓縮存儲

5.3 矩陣的壓縮存儲 矩陣是很多科學與工程計算問題中研究的數學對象&#xff0c;在此&#xff0c;我們討論如何存儲矩陣的元&#xff0c;從而使矩陣的各種運算能有效第進行。對于一個矩陣結構顯然用一個二維數組來表示是非常恰當的&#xff0c;但在有些情況下&#xff0c;比如常…

網絡工程師還要學linux嗎,網絡工程師要學什么

想成為一個優秀的網絡工程師&#xff0c;要學什么&#xff0c;怎么學呢?今天小編帶你了解一下網絡工程師到底要學什么。上篇我們講到了“網絡工程師發展方向”&#xff0c;列舉了許多技術方向&#xff0c;那么我們該如何根據自己的定位選擇學習哪些技術。重點是哪些&#xff0…

利用FormData對象實現AJAX文件上傳功能及后端實現

包括HTML基礎設置、CSS界面優化、JS利用FormData對象和AJAX進行上傳、后端接收文件并存儲到指定路徑以及刪除文件操作。FE HTML 基礎的設置&#xff1a; <form enctype"multipart/form-data"><input id"file" type"file" multiple"…

第 6 章 —— 裝飾模式

6.6 裝扮模式總結 裝飾模式把每個要裝飾的功能放在單獨的類中&#xff0c;并讓這個類包裝它所要裝飾的對象&#xff0c;因此&#xff0c;當需要執行特殊行為時&#xff0c;客戶端代碼就可以在運行時根據需要有選擇地、按順序地使用裝飾功能包裝對象了。 裝扮模式是為已有功能動…

廣義表及其存儲方式簡介

廣義表&#xff08;Lists&#xff0c;又稱列表&#xff09;是線性表的推廣。線性表定義為n>0個元素a1,a2,a3,…,an的有限序列。線性表的元素僅限于原子項&#xff0c;原子是作為結構上不可分割的成分&#xff0c;它可以是一個數或一個結構&#xff0c;若放松對表元素的這種限…

Vue.js:路由

ylbtech-Vue.js&#xff1a;路由1.返回頂部 1、Vue.js 路由 本章節我們將為大家介紹 Vue.js 路由。 Vue.js 路由允許我們通過不同的 URL 訪問不同的內容。 通過 Vue.js 可以實現多視圖的單頁Web應用&#xff08;single page web application&#xff0c;SPA&#xff09;。 Vue.…

圖片轉excel:“保留數字格式”在什么場景下該勾

保留數字格式是什么意思呢&#xff1f;顧名思義&#xff0c;就是將轉出來的數字保留為數字格式&#xff0c;而不是文本格式。我們知道&#xff0c;OCR程序將圖片上的文字識別為電腦可編輯的文字后&#xff0c;如果導入到excel不加處理&#xff0c;則單個數字過長的文字就會被ex…

html概述和基本結構

html概述 HTML是 HyperText Mark-up Language 的首字母簡寫&#xff0c;意思是超文本標記語言&#xff0c;超文本指的是超鏈接&#xff0c;標記指的是標簽&#xff0c;是一種用來制作網頁的語言&#xff0c;這種語言由一個個的標簽組成&#xff0c;用這種語言制作的文件保存的是…

linux添加三權,基于SELinux的三權分離技術的研究

目前&#xff0c;Linux操作系統已廣泛應用于各種設備和產品中&#xff0c;如服務器、PC機、機頂盒及路由器等。隨著Linux系統的不斷發展和廣泛應用&#xff0c;Linux系統的安全問題也引起越來越多的關注。在Linux操作系統中&#xff0c;存在一個超級用戶即root用戶。root也稱為…

二叉樹、樹和有序樹的區別

樹&#xff1a;子樹沒有左右之分 二叉樹、有序樹:左右有序 二叉樹與有序樹&#xff1a;在只有一棵樹的情況下&#xff0c;二叉樹有左右之分、有序樹無左右之分 另外&#xff1a;二叉樹是有序的&#xff0c;可以為空或一個根節點以及兩個分別稱為左子樹和右子樹的互不相交的二叉…

高效程序員

軟件開發人員的作戰手冊 - 讓程序員活的久一點 1. 程序員的職業準則是&#xff1a;誠實&#xff08;如實的報告你的狀態&#xff0c;風險和出現的問題&#xff09;&#xff0c;守信&#xff08;承諾完成的任務就要按時完成&#xff09;&#xff0c;尊重&#xff08;尊重給你的代…

PHP學習筆記1

1.什么是PHP&#xff1f; Hypertext Preprocessor(超文本預處理語言)。 是腳本語言。 是最流行的網站開發語言。 2.PHP能做什么&#xff1f; 可以生成動態頁面內容。 可以創建、打開、讀取、寫入、關閉服務器上的文件。 可以手機表單數據。 可以發送和接收cookies。&#xf…

Redis在windows下的配置

原文:Redis在windows下的配置 Redis在windows下的配置&#xff08;在windows-64下安裝redis&#xff0c;請參考微軟redis的github&#xff1a;https://github.com/MSOpenTech/redis/releases&#xff09;下面是windows32的配置 下載地址http://files.cnblogs.com/files/cuiweny…

linux磁盤符變化autofs,Linux基礎教程學習筆記之Autofs自動掛載

Linux基礎教程學習筆記之Autofs自動掛載Autofs自動掛載&#xff1a;yum -y install autofsvim /etc/auto.master 在文件中添加下面行/home/guests /etc/auto.tianyunvim /etc/auto.tianyun 子掛載點監控ldapuser0 -rw,sync classroom:/home/guests/ldapuser0systemctl enable …

二叉樹的遞歸遍歷(先序,中序,后序)

#include "stdio.h" #include "malloc.h" #define M 100 typedef struct node { /* 采用二叉鏈表存儲結構 */char data;struct node *lchild,*rchild; }BTnode; BTnode *create()/*利用先序遍歷的過程創建二叉樹*/ {BTnode *t;char ch;scanf("%c&quo…

DOM-動態操作心得

這個知識點都是之前看過的,就當是復習了 一、創建元素的三種方法 第一種: document.write() 識別標簽但會覆蓋之前內容第二種: 用元素自身的innerHTML方法 不識別標簽但可以不覆蓋之前內容 ul.innerHTML "<li></li>"; 第三種:利用DOM自身api創建元素 …

linux探索之旅pdf,【Linux探索之旅】第四部分第一課:壓縮文件,解壓無壓力

內容簡介1、第四部分第一課&#xff1a;壓縮文件&#xff0c;解壓無壓力2、第四部分第二課&#xff1a;SSH連接&#xff0c;安全快捷壓縮文件&#xff0c;解壓無壓力最近小編因為換工作&#xff0c;從南法搬到巴黎。折騰了很久。網絡一直用的是公共的無線網&#xff0c;信號不行…

遍歷二叉樹的全部方法(遞歸+非遞歸)

#include<iostream> #include<queue> #include<stack> using namespace std; //二叉樹結點的描述 typedef struct BiTNode { char data; struct BiTNode *lchild, *rchild; //左右孩子 }BiTNode,*BiTree; //按先序遍…

如何在本地搭建一個Android應用crashing跟蹤系統-ACRA

https://github.com/bboyfeiyu/android-tech-frontier/tree/master/others/%E5%A6%82%E4%BD%95%E5%9C%A8%E6%9C%AC%E5%9C%B0%E6%90%AD%E5%BB%BA%E4%B8%80%E4%B8%AAAndroid%E5%BA%94%E7%94%A8crashing%E8%B7%9F%E8%B8%AA%E7%B3%BB%E7%BB%9F%EF%BC%8DACRA 如何在本地搭建一個Andr…