自定义数字键盘

自定义键盘:
重写的Popupwindow,将自定义的键盘放到里面,然后屏蔽系统键盘,就能使用自定义的键盘了。

功能:

输入框弹出自定义键盘

点击屏幕或者back键,退出键盘


效果:

弹出框:

package com.risetek.nfc.ui.widget;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.os.Build;
import android.text.Editable;
import android.text.InputType;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.PopupWindow;

import com.risetek.nfc.R;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * Created by kmje on 2015/2/26.
 * 自定义数字键盘
 */
public class PopupKeyboardDialog extends PopupWindow implements PopupWindow.OnDismissListener {

    private Context mcontext;
    private int scrolldis = 0;
    public static int screenw = -1;//未知宽高
    public static int screenh = -1;
    public static int screenh_nonavbar = -1;    //不包含导航栏的高度
    public static int real_scontenth = -1;    //实际内容高度,  计算公式:屏幕高度-导航栏高度-电量栏高度
    public static float density = 1.0f;
    public static int densityDpi = 160;

    private View mContentView;
    private View mPopupView;
    private KeyboardView keyboardView;
    private Keyboard keyBoard;
    private EditText editText;

    public PopupKeyboardDialog(Context context) {
        super(context);
    }

    public PopupKeyboardDialog(Context context, EditText editText) {
        super(context);
        this.mcontext = context;
        this.editText = editText;
        initScreenParams(mcontext);
        //获取布局 lay_linear为移动的布局,因为有些设计不想移动标题栏的布局,而是移动其下面的布局
        if (null == (mContentView = ((Activity) context).findViewById(R.id.lay_linear))) {
            mContentView = ((Activity) context).getWindow().getDecorView().findViewById(Window.ID_ANDROID_CONTENT);
        }

        mPopupView = LayoutInflater.from(mcontext).inflate(
                R.layout.dialog_popupkeyboard, null);

        keyBoard = new Keyboard(mcontext, R.xml.symbols_num);
        keyboardView = (KeyboardView) mPopupView
                .findViewById(R.id.keyboard_view);
        keyboardView.setEnabled(true);
        keyboardView.setKeyboard(keyBoard);
        keyboardView.setPreviewEnabled(false);
        keyboardView.setOnKeyboardActionListener(actionListener);

        this.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
        this.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
        this.setFocusable(false);
        this.setOutsideTouchable(false);
        this.update();
        ColorDrawable dw = new ColorDrawable(0000000000);
        this.setBackgroundDrawable(dw);

        setContentView(mPopupView);

        setAnimationStyle(R.style.keyboard_popup);
        this.setOnDismissListener(this);
        int[] pos = new int[2];
        editText.getLocationOnScreen(pos);
        float height = dip2px(300);
        Rect outRect = new Rect();
        ((Activity) mcontext).getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect);

        int screen = real_scontenth;
        scrolldis = (int) ((pos[1] + editText.getMeasuredHeight() - outRect.top) - (screen - height)) + 120;

        if (scrolldis > 0) {
            mContentView.scrollBy(0, scrolldis);
        }
    }

    private KeyboardView.OnKeyboardActionListener actionListener = new KeyboardView.OnKeyboardActionListener() {
        @Override
        public void swipeUp() {
        }

        @Override
        public void swipeRight() {
        }

        @Override
        public void swipeLeft() {
        }

        @Override
        public void swipeDown() {
        }

        @Override
        public void onText(CharSequence text) {
        }

        @Override
        public void onRelease(int primaryCode) {
        }

        @Override
        public void onPress(int primaryCode) {
        }

        @Override
        public void onKey(int primaryCode, int[] keyCodes) {
            int start = editText.getSelectionStart();
            Editable editable = editText.getEditableText();
            // 删除
            if (primaryCode == Keyboard.KEYCODE_DELETE) {
                if (editable != null && editable.length() > 0) {
                    if (start > 0) {
                        editable.delete(start - 1, start);
                    }
                }
            }
            // 完成 收起键盘
            else if (primaryCode == -3) {
                PopupKeyboardDialog.this.dismiss();
            }
            // 输入
            else { // 将要输入的数字现在编辑框中
                editable.insert(start, Character.toString((char) primaryCode));
            }

        }

    };

    private void initScreenParams(Context context) {
        DisplayMetrics dMetrics = new DisplayMetrics();
        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display display = windowManager.getDefaultDisplay();
        display.getMetrics(dMetrics);

        screenw = dMetrics.widthPixels;
        screenh = dMetrics.heightPixels;
        density = dMetrics.density;
        densityDpi = dMetrics.densityDpi;

        screenh_nonavbar = screenh;

        int ver = Build.VERSION.SDK_INT;

        // 新版本的android 系统有导航栏,造成无法正确获取高度
        if (ver == 13) {
            try {
                Method mt = display.getClass().getMethod("getRealHeight");
                screenh_nonavbar = (Integer) mt.invoke(display);
            } catch (Exception e) {
            }
        } else if (ver > 13) {
            try {
                Method mt = display.getClass().getMethod("getRawHeight");
                screenh_nonavbar = (Integer) mt.invoke(display);
            } catch (Exception e) {
            }
        }

        real_scontenth = screenh_nonavbar - getStatusBarHeight(context);


    }

    /**
     * 电量栏高度
     *
     * @return
     */
    public static int getStatusBarHeight(Context context) {
        Class<?> c = null;
        Object obj = null;
        Field field = null;
        int x = 0,
                sbar = 0;
        try {
            c = Class.forName("com.android.internal.R$dimen");
            obj = c.newInstance();
            field = c.getField("status_bar_height");
            x = Integer.parseInt(field.get(obj).toString());
            sbar = context.getResources().getDimensionPixelSize(x);
        } catch (Exception e1) {
            e1.printStackTrace();
        }

        return sbar;
    }

    private int dip2px(float dipValue) {
        final float scale = mcontext.getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }

    private boolean isFlyme() {
        try {
            Method method = Build.class.getMethod("hasSmartBar");
            return method != null;
        } catch (final Exception e) {
            return false;
        }
    }

    @Override
    public void onDismiss() {
        if (scrolldis > 0) {
            if (null != mContentView) {
                mContentView.scrollBy(0, -scrolldis);
            }
        }
    }
}

 界面: 

public class MainActivity extends BaseActivity {
	private MainActivity mcontext;
	private EditText input;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mcontext = this;

		findViewById(R.id.button1).setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				send("btn");
			}
		});

		input = (EditText) findViewById(R.id.et_put);
		// 自定义键盘
		setShowKeyboardDialog(mcontext, input);
	}
}

基类:

// 隐藏系统键盘
    public void hideSoftInputMethod(EditText ed) {
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

        int currentVersion = android.os.Build.VERSION.SDK_INT;
        String methodName = null;
        if (currentVersion >= 16) {
            // 4.2
            methodName = "setShowSoftInputOnFocus";
        } else if (currentVersion >= 14) {
            // 4.0
            methodName = "setSoftInputShownOnFocus";
        }

        if (methodName == null) {
            ed.setInputType(InputType.TYPE_NULL);
        } else {
            Class<EditText> cls = EditText.class;
            Method setShowSoftInputOnFocus;
            try {
                setShowSoftInputOnFocus = cls.getMethod(methodName, boolean.class);
                setShowSoftInputOnFocus.setAccessible(true);
                setShowSoftInputOnFocus.invoke(ed, false);
            } catch (NoSuchMethodException e) {
                ed.setInputType(InputType.TYPE_NULL);
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    /**
     * 调用 自定义数字键盘
     *
     * @param mcontext
     * @param editText
     */
    protected void setKeyBoardDialog(final Context mcontext, final EditText editText) {
//        editText.setInputType(InputType.TYPE_NULL);
        //解决显示光标的问题
        hideSoftInputMethod(editText);

        editText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (null == popupWinowKeyboard || !popupWinowKeyboard.isShowing()) {
                    hideSoftInput();
                    popupWinowKeyboard = new PopupKeyboardDialog(mcontext, editText);
                    popupWinowKeyboard.showAtLocation(((Activity) mcontext)
                            .getWindow().getDecorView(), Gravity.BOTTOM, 0, 0);
                }
            }
        });

        editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View view, boolean b) {
                if (b) {
                    if (null == popupWinowKeyboard) {
                        hideSoftInput();
                        popupWinowKeyboard = new PopupKeyboardDialog(mcontext, editText);
                        popupWinowKeyboard.showAtLocation(((Activity) mcontext)
                                .getWindow().getDecorView(), Gravity.BOTTOM, 0, 0);
                    }
                } else {
                    if (null != popupWinowKeyboard) {
                        popupWinowKeyboard.dismiss();
                        popupWinowKeyboard = null;
                    }
                }
            }
        });
    }

    /**
     * 在触摸屏幕的事件中  关掉自定义键盘
     */
    protected void setInonTouchEvent() {
        if (null != popupWinowKeyboard) {
            popupWinowKeyboard.dismiss();
            popupWinowKeyboard = null;
        }
    }

@Override
    public boolean onTouchEvent(MotionEvent event) {
        setInonTouchEvent();
        return super.onTouchEvent(event);
    }
  @Override
    protected void onStop() {
        super.onStop();
        hideSoftInput();
        setInonTouchEvent();
    }

 边框: 

<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <!-- 边线 -->
    <item>
        <shape>
            <solid android:color="#ffffff" />
        </shape>
    </item>
    <!-- 背景 -->
    <item
        android:left="1px"
        android:top="1px">

        <!-- 双边  android:right="1px"    android:bottom="1px" -->
        <shape>
            <solid android:color="#00ff00" />
        </shape>
    </item>

</layer-list>
demo


注意:
1.因为布局等考虑的是dp,而scroll移动是按像素移动,所以计算时要将dp转为px。

2.如果想让光标闪动,并且屏蔽系统键盘:

      // 隐藏系统键盘
    public void hideSoftInputMethod(EditText ed){
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); 
         
        int currentVersion = android.os.Build.VERSION.SDK_INT;
        String methodName = null;
        if(currentVersion >= 16){
            // 4.2
            methodName = "setShowSoftInputOnFocus";
        }
        else if(currentVersion >= 14){
            // 4.0
            methodName = "setSoftInputShownOnFocus";
        }
         
        if(methodName == null){
            ed.setInputType(InputType.TYPE_NULL);  
        }
        else{
            Class<EditText> cls = EditText.class;  
            Method setShowSoftInputOnFocus;  
            try {
                setShowSoftInputOnFocus = cls.getMethod(methodName, boolean.class);
                setShowSoftInputOnFocus.setAccessible(true);  
                setShowSoftInputOnFocus.invoke(ed, false); 
            } catch (NoSuchMethodException e) {
                ed.setInputType(InputType.TYPE_NULL);
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }  
        }  
    }

3.对于有smartBar的手机,移动根布局可能不咋同,那么就不要移动跟布局,给要移动view添加一个id,然后移动该view就可以了。

  if (null == (mContentView = ((Activity) context).findViewById(R.id.lay_linear))) {
            mContentView = ((Activity) context).getWindow().getDecorView().findViewById(Window.ID_ANDROID_CONTENT);
        }

        mPopupView = LayoutInflater.from(mcontext).inflate(
                R.layout.dialog_popupkeyboard, null);

4.Unable to add window -- token null is not valid; is your activity running?

等视图创建完成后,才能响应事件。

@Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            initView();
        }
    }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值