说实话这个自定义数字键盘有点丑,哈哈哈哈哈。。。。。。
自定义view
public class CustomNumericKeyboardView extends View {
private Paint paint;
private int width,height; /*父容器的宽高*/
private int rectWidth,rectHeight; /*按键的宽高*/
private boolean isInit = false;
private float xOne,xTwo,xThree; /*第一列第二列第三列按键,x轴中心点坐标*/
private float yOne,yTwo,yThree,yFour,yFive; /*第一行到第五行按键,y轴中心点坐标*/
private Bitmap bitmap; /*获取图片*/
private int bitmapWidth,bitmapHeight; /*获取图片的宽高*/
private Bitmap newBitmap; /*二次采样后获取新的图片*/
private String number; /*点击按键返回当前值*/
private RectF rectF; /*按下和抬起时,当前按键左上右下的位置*/
private RectF rectF1_1; /*第一列第一行按键 左上右下的位置*/
private RectF rectF1_2;
private RectF rectF1_3;
private RectF rectF1_4;
private RectF rectF1_5;
private RectF rectF2_1; /*第二列第一行按键 左上右下的位置*/
private RectF rectF2_2;
private RectF rectF2_3;
private RectF rectF2_4;
private RectF rectF2_5;
private RectF rectF3_1; /*第三列第一行按键 左上右下的位置*/
private RectF rectF3_2;
private RectF rectF3_3;
private RectF rectF3_4;
private RectF rectF3_5;
private float distance; /*字体默认在坐标右侧,设置居中的其中一个值*/
private OnNumberClickListener onNumberClickListener;/*对外提供的点击事件*/
private boolean isLongClickModule=false; /*判断是删除还是长按删除*/
/*
*事件分发
* type=-1 初始化
* type=0 按下时刷新
* type=1 抬起时刷新
* */
private int type=-1;
Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what==0){
isLongClickModule = true;/*判断是长按删除*/
onNumberClickListener.onNumberDelete();/*长按删除*/
handler.sendEmptyMessageDelayed(0,100);/*删除间隔100毫秒*/
}
}
};
/*
* Custom [ˈkʌstəm] 自定义(克斯特m)
* Numeric [njuː'merɪk]数字(niu迈瑞克)
* Keyboard [ˈkiːbɔːd] 键盘(ki暴的)
* */
public CustomNumericKeyboardView(Context context) {
super(context);
}
public CustomNumericKeyboardView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public CustomNumericKeyboardView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public CustomNumericKeyboardView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public OnNumberClickListener getOnNumberClickListener(){
return onNumberClickListener;
}
public void setOnNumberClickListener(OnNumberClickListener onNumberClickListener){
this.onNumberClickListener = onNumberClickListener;
}
@SuppressLint("ResourceAsColor")
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onDraw(Canvas canvas) {/*按下抬起都会走onDraw(Canvas canvas)*/
super.onDraw(canvas);
if (!isInit) {/*是否初始化*/
initData();
}
drawKeyboard(canvas);/*画出按键和数字*/
if (type==0){/*按下时*/
/*值不为空,画出对应的按键和值(先看事件分发按下时里面的setNumeric(x,y);方法,方法里是返回number值的)*/
if (number!=null){/*每个按键之间的边距为10,所以当按在边距上返回null,这地方不做判断报错空指针异常*/
paint.setColor(Color.GRAY);/*字体颜色为黑色*/
canvas.drawRoundRect(rectF, 10,10,paint);
paint.setColor(Color.BLACK);
paint.setTextSize(60);// 设置字体大小
/*设置画笔宽度,中间漏空情况下,画笔宽度=左边宽度+右边宽度 同理上下高度也是如此*/
paint.setStrokeWidth(2);
if (number.equals("hide")){
canvas.drawText("隐藏", rectF.centerX(), rectF.centerY()+ distance, paint);
}else if (number.equals("dial")){
canvas.drawBitmap(newBitmap, (rectWidth * 3) / 2- newBitmap.getWidth()/2 + 20,
(rectHeight * 9) / 2- newBitmap.getHeight()/2 + 50, paint);
}else if (number.equals("delete")){
canvas.drawText("删除", rectF.centerX(), rectF.centerY()+ distance, paint);
}else {
canvas.drawText(number, rectF.centerX(), rectF.centerY()+ distance, paint);
}
Log.d("++++++++if (type==0)",type+"");
}
}else if (type==1){/*抬起*/
if (number!=null){/*值不为空,画出对应的按键和值*/
paint.setColor(Color.WHITE);
canvas.drawRoundRect(rectF, 10,10,paint);
paint.setColor(Color.BLACK);
paint.setTextSize(60);// 设置字体大小
paint.setStrokeWidth(2);
if (number.equals("hide")){
canvas.drawText("隐藏", rectF.centerX(), rectF.centerY()+ distance, paint);
}else if (number.equals("dial")){
canvas.drawBitmap(newBitmap, (rectWidth * 3) / 2- newBitmap.getWidth()/2 + 20,
(rectHeight * 9) / 2- newBitmap.getHeight()/2 + 50, paint);
}else if (number.equals("delete")){
canvas.drawText("删除", rectF.centerX(), rectF.centerY()+ distance, paint);
}else {
canvas.drawText(number, rectF.centerX(), rectF.centerY()+ distance, paint);
}
Log.d("++++++++if (type==1)",type+"");
}
}
}
private void initData() {
paint = new Paint();
/*获取父容器的宽和高*/
width = getWidth();
height = getHeight();
/*获取图片*/
bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.dial_img);
bitmapWidth = bitmap.getWidth();
bitmapHeight = bitmap.getHeight();
//设置想要的大小 二次采样
int newWidth= 100;
int newHeight=100;
//计算压缩的比率
float scaleWidth=((float)newWidth)/bitmapWidth;
float scaleHeight=((float)newHeight)/bitmapHeight;
//获取想要缩放的matrix
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth,scaleHeight);
//获取新的bitmap(二次采样后的图片)
newBitmap = Bitmap.createBitmap(this.bitmap, 0, 0, bitmapWidth, bitmapHeight, matrix, true);
newBitmap.getWidth(); /*新的宽*/
newBitmap.getHeight(); /*新的高*/
/*计算矩形的宽和高(数字键盘按键的宽和高)*/
rectWidth = (this.width - 40) / 3;
rectHeight = (this.height - 60) / 5;
/*第一列第二列第三列按键,x轴中心点坐标*/
xOne = rectWidth / 2 + 10;
xTwo = (rectWidth * 3) / 2 + 20;
xThree = (rectWidth * 5) / 2 + 30;
/*第一行到第五行按键,y轴中心点坐标*/
yOne = rectHeight / 2 + 10;
yTwo = (rectHeight * 3) / 2 + 20;
yThree = (rectHeight * 5) / 2 + 30;
yFour = (rectHeight * 7) / 2 + 40;
yFive = (rectHeight * 9) / 2 + 50;
isInit = true;/*初始化完成*/
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void drawKeyboard(Canvas canvas) {
paint.setColor(Color.WHITE);
/*第一列 只需要改变top和bottom*/
rectF1_1 = new RectF(10, 10, 10 + rectWidth, 10 + rectHeight);
canvas.drawRoundRect(rectF1_1, 10,10,paint);
rectF1_2 = new RectF(10, 20 + rectHeight * 1, 10 + rectWidth, 20 + rectHeight * 2);
canvas.drawRoundRect(rectF1_2,10,10,paint);
rectF1_3 = new RectF(10, 30 + rectHeight * 2, 10 + rectWidth, 30 + rectHeight * 3);
canvas.drawRoundRect(rectF1_3,10,10,paint);
rectF1_4 = new RectF(10, 40 + rectHeight * 3, 10 + rectWidth, 40 + rectHeight * 4);
canvas.drawRoundRect(rectF1_4,10,10,paint);
rectF1_5 = new RectF(10, 50 + rectHeight * 4, 10 + rectWidth, 50 + rectHeight * 5);
canvas.drawRoundRect(rectF1_5,10,10,paint);
/*第二列*/
rectF2_1 = new RectF(20 + rectWidth, 10, 20 + rectWidth * 2, 10 + rectHeight);
canvas.drawRoundRect(rectF2_1,10,10,paint);
rectF2_2 = new RectF(20 + rectWidth, 20 + rectHeight * 1, 20 + rectWidth * 2, 20 + rectHeight * 2);
canvas.drawRoundRect(rectF2_2,10,10,paint);
rectF2_3 = new RectF(20 + rectWidth, 30 + rectHeight * 2, 20 + rectWidth * 2, 30 + rectHeight * 3);
canvas.drawRoundRect(rectF2_3,10,10,paint);
rectF2_4 = new RectF(20 + rectWidth, 40 + rectHeight * 3, 20 + rectWidth * 2, 40 + rectHeight * 4);
canvas.drawRoundRect(rectF2_4,10,10,paint);
rectF2_5 = new RectF(20 + rectWidth, 50 + rectHeight * 4, 20 + rectWidth * 2, 50 + rectHeight * 5);
canvas.drawRoundRect(rectF2_5,10,10,paint);
/*第三列*/
rectF3_1 = new RectF(30 + rectWidth * 2, 10, 30 + rectWidth * 3, 10 + rectHeight);
canvas.drawRoundRect(rectF3_1,10,10,paint);
rectF3_2 = new RectF(30 + rectWidth * 2, 20 + rectHeight * 1, 30 + rectWidth * 3, 20 + rectHeight * 2);
canvas.drawRoundRect(rectF3_2,10,10,paint);
rectF3_3 = new RectF(30 + rectWidth * 2, 30 + rectHeight * 2, 30 + rectWidth * 3, 30 + rectHeight * 3);
canvas.drawRoundRect(rectF3_3,10,10,paint);
rectF3_4 = new RectF(30 + rectWidth * 2, 40 + rectHeight * 3, 30 + rectWidth * 3, 40 + rectHeight * 4);
canvas.drawRoundRect(rectF3_4,10,10,paint);
rectF3_5 = new RectF(30 + rectWidth * 2, 50 + rectHeight * 4, 30 + rectWidth * 3, 50 + rectHeight * 5);
canvas.drawRoundRect(rectF3_5,10,10,paint);
/*画上数字*/
paint.setColor(Color.BLACK);
paint.setTextSize(60);
paint.setStyle(Paint.Style.FILL);
paint.setTextAlign(Paint.Align.CENTER);
//计算baseline
Paint.FontMetrics fontMetrics=paint.getFontMetrics();
distance = (fontMetrics.bottom - fontMetrics.top)/2 - fontMetrics.bottom;
float baseline= rectF1_1.centerY()+ distance;
canvas.drawText("1", rectF1_1.centerX(),baseline,paint);
float baseline1_2= rectF1_2.centerY()+ distance;
canvas.drawText("4", rectF1_2.centerX(),baseline1_2,paint);
float baseline1_3= rectF1_3.centerY()+ distance;
canvas.drawText("7", rectF1_3.centerX(),baseline1_3,paint);
float baseline1_4= rectF1_4.centerY()+ distance;
canvas.drawText("*", rectF1_4.centerX(),baseline1_4,paint);
float baseline1_5= rectF1_5.centerY()+ distance;
canvas.drawText("隐藏", rectF1_5.centerX(),baseline1_5,paint);
float baseline2_1= rectF2_1.centerY()+ distance;
canvas.drawText("2", rectF2_1.centerX(),baseline2_1,paint);
float baseline2_2= rectF2_2.centerY()+ distance;
canvas.drawText("5", rectF2_2.centerX(),baseline2_2,paint);
float baseline2_3= rectF2_3.centerY()+ distance;
canvas.drawText("8", rectF2_3.centerX(),baseline2_3,paint);
float baseline2_4= rectF2_4.centerY()+ distance;
canvas.drawText("0", rectF2_4.centerX(),baseline2_4,paint);
canvas.drawBitmap(newBitmap, (rectWidth * 3) / 2- newBitmap.getWidth()/2 + 20, (rectHeight * 9) / 2- newBitmap.getHeight()/2 + 50, paint);
float baseline3_1= rectF3_1.centerY()+ distance;
canvas.drawText("3", rectF3_1.centerX(),baseline3_1,paint);
float baseline3_2= rectF3_2.centerY()+ distance;
canvas.drawText("6", rectF3_2.centerX(),baseline3_2,paint);
float baseline3_3= rectF3_3.centerY()+ distance;
canvas.drawText("9", rectF3_3.centerX(),baseline3_3,paint);
float baseline3_4= rectF3_4.centerY()+ distance;
canvas.drawText("#", rectF3_4.centerX(),baseline3_4,paint);
float baseline3_5= rectF3_5.centerY()+ distance;
canvas.drawText("删除", rectF3_5.centerX(),baseline3_5,paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();//事件监听x轴
float y = event.getY();//事件监听y轴
switch (event.getAction()){
case MotionEvent.ACTION_DOWN://按下
setDefault();//初始化
setNumeric(x,y);//返回数字
if (number!=null){
if (number.equals("hide")){
onNumberClickListener.onHideKeyboard();
type =1;//调完隐藏方法让它做抬起动作
invalidate();
setDefault();//初始化
}else if (number.equals("dial")){
onNumberClickListener.onDialKey();
}else if (number.equals("delete")){
handler.sendEmptyMessageDelayed(0,500);
}else {
onNumberClickListener.onNumberReturn(number);
}
}
Log.d("+++++++setNumeric()",number+"");
type = 0;
invalidate();/*刷新*/
return true;
case MotionEvent.ACTION_UP://抬起 ACTION_POINTER_UP//再次按下前走这个抬起
handler.removeCallbacksAndMessages(null);
/*isLongClickModule=false;长按删除键会多删除一个数(不过没太大影响)*/
if (number!=null){
if (number.equals("delete")){
if (!isLongClickModule){
/*长按删除是长按时删除,删除一个数抬起时才删除*/
onNumberClickListener.onNumberDelete();
}
}
}
/*初始化*/
isLongClickModule=false;
type =1;
Log.d("++++++++ACTION_UP",type+"");
invalidate();
setDefault();//初始化
return true;
case MotionEvent.ACTION_MOVE://移动 ACTION_HOVER_MOVE 来回移动 HOVER徘徊
return true;
}
return super.onTouchEvent(event);
}
private void setDefault() {
number=null;
type =-1;
}
private void setNumeric(float x, float y) {//点击按钮返回对应的值
if (10<=x&&x<=rectWidth+10){//第一列
if (10<=y&&y<=rectHeight+10){
rectF=rectF1_1;
number = "1";
}else if (rectHeight+20<=y&&y<=rectHeight*2+20){
rectF=rectF1_2;
number = "4";
}else if (rectHeight*2+30<=y&&y<=rectHeight*3+30){
rectF=rectF1_3;
number="7";
}else if (rectHeight*3+40<=y&&y<=rectHeight*4+40){
rectF=rectF1_4;
number="*";
}else if (rectHeight*4+50<=y&&y<=rectHeight*5+50){
rectF=rectF1_5;
number="hide";
}
}if (rectWidth+20<=x&&x<=rectWidth*2+20){//第二列
if (10<=y&&y<=rectHeight+10){
rectF=rectF2_1;
number = "2";
}else if (rectHeight+20<=y&&y<=rectHeight*2+20){
rectF=rectF2_2;
number = "5";
}else if (rectHeight*2+30<=y&&y<=rectHeight*3+30){
rectF=rectF2_3;
number="8";
}else if (rectHeight*3+40<=y&&y<=rectHeight*4+40){
rectF=rectF2_4;
number="0";
}else if (rectHeight*4+50<=y&&y<=rectHeight*5+50){
rectF=rectF2_5;
number="dial";//拨号
}
}if (rectWidth*2+30<=x&&x<=rectWidth*3+30){//第三列
if (10<=y&&y<=rectHeight+10){
rectF=rectF3_1;
number = "3";
}else if (rectHeight+20<=y&&y<=rectHeight*2+20){
rectF=rectF3_2;
number = "6";
}else if (rectHeight*2+30<=y&&y<=rectHeight*3+30){
rectF=rectF3_3;
number="9";
}else if (rectHeight*3+40<=y&&y<=rectHeight*4+40){
rectF=rectF3_4;
number="#";
}else if (rectHeight*4+50<=y&&y<=rectHeight*5+50){
rectF=rectF3_5;
number="delete";//删除
}
}
}
public interface OnNumberClickListener{
//回调点击的数字
public void onNumberReturn(String number);
//回调隐藏键盘
public void onHideKeyboard();
//回调拨号键
public void onDialKey();
//删除键的回调
public void onNumberDelete();
}
}
custom_keyboard_view.xml PopupWindow布局
<自己的包名.CustomNumericKeyboardView
android:id="@+id/customNumericKeyboardView"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_300"
android:background="@color/colorAccent"/>
当前类布局
当前类
public class DialActivity extends BaseActivity {
private TextView am_tv_text;
private EditText number_text;
private Editable editable;
private int start=-1;
private View mPopupHeadViewy,view;//创建一个view
private PopupWindow mHeadPopupclly;//PopupWindow
private CustomNumericKeyboardView customNumericKeyboardView;
@Override
protected void initComponents() {
setContentView(R.layout.activity_dial);
am_tv_text = (TextView) findViewById(R.id.am_tv_text);
number_text = (EditText) findViewById(R.id.number_text);
}
@Override
protected void initData() {
popupHeadWindowcll();/*默认显示*/
am_tv_text.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
popupHeadWindowcll();
}
});
}
@TargetApi(Build.VERSION_CODES.KITKAT)
@SuppressWarnings("deprecation")
private void popupHeadWindowcll() {
if (mPopupHeadViewy==null){//为空重新创建
mPopupHeadViewy = View.inflate(BoHaoActivity.this, R.layout.custom_keyboard_view, null);
}
if (view==null){//为空重新创建
view = View.inflate(this, R.layout.activity_bo_hao, null);
}
if (mHeadPopupclly==null){//为空重新创建
mHeadPopupclly = new PopupWindow(mPopupHeadViewy, ActionBar.LayoutParams.MATCH_PARENT,
ActionBar.LayoutParams.WRAP_CONTENT,true);
}
// 在PopupWindow里面就加上下面代码,让键盘弹出时,不会挡住pop窗口。
mHeadPopupclly.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
mHeadPopupclly.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
mHeadPopupclly.setBackgroundDrawable(new BitmapDrawable());//点击空白处的时候让PopupWindow消失
mHeadPopupclly.setTouchable(true);//可触的,获取焦点
mHeadPopupclly.setOutsideTouchable(true);
number_text.post(new Runnable() {
@Override
public void run() {
//mHeadPopupclly.showAsDropDown(view, Gravity.CENTER, 0, 0);//居中
mHeadPopupclly.showAtLocation(view, Gravity.BOTTOM,0,0);//弹框底部显示
customNumericKeyboardView = (CustomNumericKeyboardView) mPopupHeadViewy.findViewById(R.id.customNumericKeyboardView);
customNumericKeyboardView.setOnNumberClickListener(new CustomNumericKeyboardView.OnNumberClickListener() {
@Override
public void onNumberReturn(String number) {
editable = number_text.getText();
start = number_text.getSelectionStart();
editable.insert(start, number);
}
@Override
public void onHideKeyboard() {
mHeadPopupclly.dismiss();/*隐藏键盘*/
}
@Override
public void onDialKey() {/*拨号*/
BaseFragment.getIntent(DialActivity.this, ContactsActivity.class);
}
@Override
public void onNumberDelete() {/*删除*/
if (editable != null && editable.length() > 0) {
if (start >=0) {
//editable.delete(start-1, start); //网上的不好使
editable.delete(start, editable.length());//start应该是数组下标,editable.length()数组长度
start--;//删除一个数,数组下标减一
Log.d("+++++editable.length()"+ TAG,editable.length()+"");
}
}
}
});
}
});
}
}
粘过去就可以显示了,有点简陋别嫌弃,需要什么样的风格自己包装,我去也.....
如果有问题还请指出,大家共同进步,抱拳了老铁