Android 實(shí)現(xiàn)數(shù)字九宮格軟鍵盤
前言
一開始大概是這種

需求
組長說 要不搞一個(gè)自定義軟鍵盤吧 數(shù)字搞大點(diǎn) 方便外賣員輸入數(shù)字
我設(shè)置了輸入EditText的輸入格式為Number 還是不行
那就開搞吧
先來看下實(shí)現(xiàn)的效果圖吧
實(shí)現(xiàn)效果GIF

實(shí)現(xiàn)代碼
自定義View 一個(gè)NineNumericKeyboardView
/**
* Author by Lyu
* Date on 2021/5/26-19:55
* Description:九宮格數(shù)字軟鍵盤
*/
public class NineNumericKeyboardView extends View {
/**
* 列
*/
private static final int TOTAL_COL = 3;
/**
* 行
*/
private static final int TOTAL_ROW = 4;
private Paint HuiseBgPaint, linePaint;
private Paint mTextPaint;
private int mViewWidth; // 鍵盤寬度
private int mViewHight; // 鍵盤高度
private float mCellWidth, mCellHight; // 單元格寬度、高度
private Row rows[] = new Row[TOTAL_ROW];
private Bitmap bitmap; // 刪除按鈕圖片
private Paint mCutTextPaint;
//回調(diào)方法
public interface CallBack {
void clickNum(String num);// 回調(diào)點(diǎn)擊的數(shù)字
void deleteNum();// 回調(diào)刪除
}
private CallBack mCallBack;// 回調(diào)
public void setOnCallBack(CallBack callBack) {
mCallBack = callBack;
}
public NineNumericKeyboardView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public NineNumericKeyboardView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public NineNumericKeyboardView(Context context) {
super(context);
init(context);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawLine(canvas);
for (int i = 0; i < TOTAL_ROW; i++) {
if (rows[i] != null)
rows[i].drawCells(canvas);
}
}
/**
* 畫6條直線
*
* @param canvas
*/
private void drawLine(Canvas canvas) {
canvas.drawLine(0, 0, mViewWidth, 0, linePaint);
canvas.drawLine(0, mCellHight, mViewWidth, mCellHight, linePaint);
canvas.drawLine(0, mCellHight * 2, mViewWidth, mCellHight * 2, linePaint);
canvas.drawLine(0, mCellHight * 3, mViewWidth, mCellHight * 3, linePaint);
canvas.drawLine(mCellWidth, 0, mCellWidth, mViewHight, linePaint);
canvas.drawLine(mCellWidth * 2, 0, mCellWidth * 2, mViewHight, linePaint);
}
/**
* 初始化畫筆
*
* @param context
*/
private void init(Context context) {
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mCutTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
linePaint.setTextSize(1.0f);
linePaint.setColor(0x90000000);
HuiseBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
HuiseBgPaint.setStyle(Paint.Style.FILL);
HuiseBgPaint.setColor(Color.parseColor("#e9e9e9"));
initDate();
}
private void initDate() {
fillDate();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mViewWidth = w;
mViewHight = h;
mCellWidth = mViewWidth / TOTAL_COL;
mCellHight = mViewHight / TOTAL_ROW;
mTextPaint.setTextSize(mCellHight / 3);
}
private Cell mClickCell = null;
private float mDownX;
private float mDownY;
/*
*
* 觸摸事件為了確定點(diǎn)擊位置的數(shù)字
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mDownX = event.getX();
mDownY = event.getY();
int col = (int) (mDownX / mCellWidth);
int row = (int) (mDownY / mCellHight);
measureClickCell(col, row);
break;
case MotionEvent.ACTION_UP:
if (mClickCell != null) {
// 在抬起后把狀態(tài)置為默認(rèn)
rows[mClickCell.i].cells[mClickCell.j].state = State.DEFAULT_NUM;
mClickCell = null;
invalidate();
}
break;
}
return true;
}
/**
* 測量點(diǎn)擊單元格
*
* @param col 列
* @param row 行
*/
private void measureClickCell(int col, int row) {
if (col >= TOTAL_COL || row >= TOTAL_ROW)
return;
if (rows[row] != null) {
mClickCell = new Cell(rows[row].cells[col].num, rows[row].cells[col].state, rows[row].cells[col].i,
rows[row].cells[col].j);
rows[row].cells[col].state = State.CLICK_NUM;
if ("-5".equals(rows[row].cells[col].num)) {
mCallBack.deleteNum();
} else {
mCallBack.clickNum(rows[row].cells[col].num);
}
invalidate();
}
}
/**
* 組 以一行為一組
*/
private class Row {
public int j;
Row(int j) {
this.j = j;
}
// 一行3個(gè)單元格
public Cell[] cells = new Cell[TOTAL_COL];
public void drawCells(Canvas canvas) {
for (int i = 0; i < cells.length; i++) {
if (cells[i] != null)
cells[i].drawSelf(canvas);
}
}
}
// 單元格
private class Cell {
public String num;
public State state;
/**
* i = 行 j = 列
*/
public int i;
public int j;
public Cell(String num, State state, int i, int j) {
super();
this.num = num;
this.state = state;
this.i = i;
this.j = j;
}
// 繪制一個(gè)單元格 如果顏色需要自定義可以修改
public void drawSelf(Canvas canvas) {
switch (state) {
case CLICK_NUM:
// 繪制點(diǎn)擊效果灰色背景
canvas.drawRect((mCellWidth * j), (mCellHight * i),
(mCellWidth * (j + 1)), (mCellHight * (i + 1)), HuiseBgPaint);
break;
}
if ("-5".equals(num)) {
// 繪制刪除圖片
canvas.drawBitmap(bitmap, (float) (mCellWidth * 2.5 - bitmap.getWidth() / 2), (float) (mCellHight * 3.5 - bitmap.getHeight() / 2), HuiseBgPaint);
} else {
// 繪制數(shù)字
canvas.drawText(num, (float) ((j + 0.5) * mCellWidth - mTextPaint.measureText(num) / 2),
(float) ((i + 0.5) * mCellHight + mTextPaint.measureText(num, 0, 1) / 2),
mTextPaint);
}
}
}
/**
* cell的state
*/
private enum State {
DEFAULT_NUM, CLICK_NUM;
}
private List<String> numKeys = Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "0");
/**
* 填充數(shù)字
*/
private void fillDate() {
int postion = 0;
for (int i = 0; i < TOTAL_ROW; i++) {
rows[i] = new Row(i);
for (int j = 0; j < TOTAL_COL; j++) {
if (i == 3 && j == 0) {
rows[i].cells[j] = new Cell(".", State.DEFAULT_NUM, i, j);
continue;
} else if (i == 3 && j == 2) {
rows[i].cells[j] = new Cell("-5", State.DEFAULT_NUM, i, j);
continue;
} else {
rows[i].cells[j] = new Cell(numKeys.get(postion), State.DEFAULT_NUM, i, j);
postion++;
}
}
}
//這里是插入一張刪除數(shù)字的圖 一般是 X
bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.keyboard_delete);
}
}
使用方法
利用android自帶的組件PopupWindow在指定頁面的下方彈出即可 完成效果
在指定的View頁面
//初始化鍵盤
private void initKeyboardView() {
// 設(shè)置不彈出系統(tǒng)鍵盤
etInputPickupCode.setInputType(InputType.TYPE_NULL);
// 自己監(jiān)聽EditText的點(diǎn)擊事件彈出我們自定義的鍵盤
etInputPickupCode.setOnClickListener(view -> mPop.showAtLocation(llKey, Gravity.BOTTOM, 0, 0));
mPop = new PopupWindow();
mPopView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.custom_keyboardview, null);
mPop.setContentView(mPopView);
mPop.setTouchable(true);
mPop.setFocusable(true);
mPop.setBackgroundDrawable(new ColorDrawable());
mPop.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
mPop.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
mCustomKeyView = mPopView.findViewById(R.id.key_view);
// 設(shè)置回調(diào),并進(jìn)行文本的插入與刪除
mCustomKeyView.setOnCallBack(this);
}
@Override
public void clickNum(String num) {
if (etInputPickupCode.getText().length() < 8) {
etInputPickupCode.append(num);
}
}
@Override
public void deleteNum() {
int last = etInputPickupCode.getText().length();
if (last > 0) {
//刪除最后一位
etInputPickupCode.getText().delete(last - 1, last);
}
}
以上就是Android 實(shí)現(xiàn)數(shù)字九宮格軟鍵盤的詳細(xì)內(nèi)容,更多關(guān)于Android 數(shù)字九宮格軟鍵盤的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android編程之TabWidget選項(xiàng)卡用法實(shí)例分析
這篇文章主要介紹了Android編程之TabWidget選項(xiàng)卡用法,結(jié)合實(shí)例形式較為詳細(xì)的分析了TabWidget選項(xiàng)卡的具體實(shí)現(xiàn)技巧與使用注意事項(xiàng),需要的朋友可以參考下2015-12-12
Android Activity啟動(dòng)模式之singleTask實(shí)例詳解
這篇文章主要介紹了Android Activity啟動(dòng)模式之singleTask,結(jié)合實(shí)例形式較為詳細(xì)的分析了singleTask模式的功能、使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2016-01-01
Android編程實(shí)現(xiàn)自動(dòng)調(diào)整TextView字體大小以適應(yīng)文字長度的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)自動(dòng)調(diào)整TextView字體大小以適應(yīng)文字長度的方法,涉及Android基于TextView類的繼承及Paint屬性操作實(shí)現(xiàn)字體大小自適應(yīng)的相關(guān)技巧,需要的朋友可以參考下2016-01-01
Android開發(fā)之開關(guān)按鈕控件ToggleButton簡單用法示例
這篇文章主要介紹了Android開發(fā)之開關(guān)按鈕控件ToggleButton簡單用法,結(jié)合實(shí)例形式分析了Android開關(guān)按鈕控件ToggleButton的相關(guān)xml布局與調(diào)用操作技巧,需要的朋友可以參考下2017-12-12
android系統(tǒng)按鍵音framework流程源碼詳細(xì)解析
這篇文章主要為大家詳細(xì)介紹了android系統(tǒng)按鍵音framework流程源碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08
Android開發(fā)之進(jìn)度條ProgressBar的示例代碼
本篇文章主要介紹了Android開發(fā)之進(jìn)度條ProgressBar的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-03-03
Android仿淘寶詳情頁面viewPager滑動(dòng)到最后一張圖片跳轉(zhuǎn)的功能
需要做一個(gè)仿淘寶客戶端ViewPager滑動(dòng)到最后一頁,再拖動(dòng)的時(shí)候跳到詳情的功能,剛開始我也迷糊了,通過查閱相關(guān)資料發(fā)現(xiàn)有好多種實(shí)現(xiàn)方法,下面小編給大家分享實(shí)例代碼,感興趣的朋友一起看看吧2017-03-03

