您的位置:首页 > 移动开发 > Android开发

android自定义数字键盘

2017-12-08 15:44 357 查看
转载请注明出处:http://blog.csdn.net/ym4189/article/details/78752334

前言

最近需要做一个自定义的数字键盘,开始使用了下系统自带的KeyBoardView,但是发现UI效果不是很理想,最后还是自己画一个自定义键盘,这样在UI方面更加方便。先看效果图吧:



思路

1.键盘4行*3列的布局分为12个单元格,6条直线分隔单元格。根据单元格宽高确定数字位置。

2.点击效果根据用户按下和抬起动作做不同标记。

思路说的有点模糊,直接看代码吧,代码里的注释很详细:

实现

1:自定义view–CustomNumKeyView

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class CustomNumKeyView 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; // 删除按钮图片

public interface CallBack {
void clickNum(String num);// 回调点击的数字
void deleteNum();// 回调删除
}

private CallBack mCallBack;// 回调

public void setOnCallBack(CallBack callBack) {
mCallBack = callBack;
}

public CustomNumKeyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);

}

public CustomNumKeyView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);

}

public CustomNumKeyView(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 canvas
*/
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;

/*
*
* 触摸事件为了确定点击位置的数字
*/
@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) {
// 在抬起后把状态置为默认
rows[mClickCell.i].cells[mClickCell.j].state = State.DEFAUL
e497
T_NUM;
mClickCell = null;
invalidate();
}
break;
}
return true;
}

/**
* 测量点击单元格
* @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个单元格
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;
}

// 绘制一个单元格 如果颜色需要自定义可以修改
public void drawSelf(Canvas canvas) {
switch (state) {
case CLICK_NUM:
// 绘制点击效果灰色背景
canvas.drawRect((float) (mCellWidth * j), (float) (mCellHight * i),
(float) (mCellWidth * (j + 1)), (float) (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 {
// 绘制数字
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");

/**
* 填充数字
*/
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++;
}
}
}
bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.icon_cancel);
}

/**
* 随机键盘
* @param isRandom
*/
public void setRandomKeyBoard(boolean isRandom) {
if (isRandom) {
Collections.shuffle(numKeys);
initDate();
invalidate();
}
}

}


这里主要就是要注意单元格的绘制坐标,代码应该很好理解。

键盘已经画好,接下来就是使用了:

2.MainActivity

package net.yangming.numkeyboard;

import android.graphics.drawable.ColorDrawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.InputType;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.PopupWindow;

public class MainActivity extends AppCompatActivity implements NumKeyView.OnKeyPressListener, CustomNumKeyView.CallBack {
private EditText mEditText;
private NumKeyView mKeyView;
private CustomNumKeyView mCustomKeyView;
private LinearLayout mLinearlayout;
private PopupWindow mPop;
private View mPopView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}

private void initView() {
mLinearlayout = (LinearLayout) findViewById(R.id.linear);
mEditText = (EditText) findViewById(R.id.edit);
// 设置不弹出系统键盘
mEditText.setInputType(InputType.TYPE_NULL);
// 自己监听EditText的点击事件弹出我们自定义的键盘
mEditText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mPop.showAtLocation(mLinearlayout, Gravity.BOTTOM, 0, 0);
}
});
mPop = new PopupWindow();
//        mCustomKeyView=new CustomNumKeyView(this);
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 = (CustomNumKeyView) mPopView.findViewById(R.id.keyboardview);
// 设置回调,并进行文本的插入与删除
mCustomKeyView.setOnCallBack(this);
}

public void OnButtonClick(View view) {
switch (view.getId()) {
case R.id.btn_default:
mCustomKeyView.setRandomKeyBoard(false);
break;
case R.id.btn_random:
// 设置随机数字键盘
mCustomKeyView.setRandomKeyBoard(true);
break;
}
}

@Override
public void clickNum(String num) {
if (mEditText.getText().length() < 6) {
mEditText.append(num);
//文本长度为6时隐藏键盘
if (mEditText.getText().length() == 6) {
mPop.dismiss();
}
}
}

@Override
public void deleteNum() {
int last = mEditText.getText().length();
if (last > 0) {
//删除最后一位
mEditText.getText().delete(last - 1, last);
}
}
}


3.custom_keyboardview

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<net.yangming.numkeyboard.CustomNumKeyView
android:id="@+id/keyboardview"
android:layout_width="match_parent"
android:layout_height="200dp" />
</LinearLayout>


好了,自定义键盘就完成了 >_<

ps:

我这里只是做了最简单的键盘,主要是讲解实现的方法和思路。你们可以根据自己的需求画出不同的UI效果和点击效果。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息