自定义数字键盘

 说实话这个自定义数字键盘有点丑,哈哈哈哈哈。。。。。。

自定义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"/>

当前类布局

<EditText
        android:id="@+id/number_text"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_50"
        android:layout_marginTop="@dimen/dp_100"
        android:gravity="center"
        android:focusable="false"
        android:background="@color/head_background" />
    <TextView
        android:id="@+id/am_tv_text"
        android:layout_width="@dimen/dp_50"
        android:layout_height="@dimen/dp_50"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_marginBottom="@dimen/dp_50"
        android:layout_marginRight="@dimen/dp_50"
        android:background="@color/head_background"
        android:gravity="center"
        android:text="显示"/>

当前类

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()+"");
                            }
                        }
                    }
                });
            }
        });
    }

}

粘过去就可以显示了,有点简陋别嫌弃,需要什么样的风格自己包装,我去也.....

如果有问题还请指出,大家共同进步,抱拳了老铁

发布了21 篇原创文章 · 获赞 8 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/wei844067872/article/details/105161923