数字键盘的输入连接

时间:2017-07-07 11:10:48

标签: android keyboard

我做了我的自定义PIN码视图

class StarsPasswordView : LinearLayout {

    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
        init(context, attrs)
    }

    val passwordHolder = SpannableStringBuilder()

    var count

    fun init(context: Context, attrs: AttributeSet?) {
        orientation = HORIZONTAL
        isFocusable = true
        isFocusableInTouchMode = true
        gravity = Gravity.CENTER

        val attr = context.obtainStyledAttributes(attrs, R.styleable.StarsPasswordView, 0, 0)
        count = attr.getInteger(R.styleable.StarsPasswordView_count, 4)
        attr.recycle()

        drawView(count)

        setOnKeyListener(View.OnKeyListener { v, keyCode, event ->
            if (event.action == KeyEvent.ACTION_DOWN) {
                if (keyCode == KeyEvent.KEYCODE_ENTER)
                    return@OnKeyListener true
                if (keyCode == KeyEvent.KEYCODE_BACK)
                    return@OnKeyListener false
                if (keyCode == KeyEvent.KEYCODE_DEL) {
                    clear()
                    get(0).requestFocus()
                } else
                    if (passwordHolder.length != count) {
                        passwordHolder.append(event.number)
                        val position = passwordHolder.length
                        select(position - 1)

                        if (position < count)
                            get(position).requestFocus()
                        else {
                            passwordFilled?.invoke(passwordHolder.toString())
                        }
                    }
                return@OnKeyListener true
            }
            false
        })
    }

    fun samsungWorkaround() {
        val position = passwordHolder.length
        select(position - 1)

        if (position == count)
            passwordFilled?.invoke(passwordHolder.toString())
        }
    }


    // toggle whether the keyboard is showing when the view is clicked
    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (enableKeyboard && event.action == MotionEvent.ACTION_UP) {
            val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
            imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, InputMethodManager.HIDE_IMPLICIT_ONLY)
        }
        return true
    }

    override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection {
        outAttrs.inputType = InputType.TYPE_CLASS_NUMBER
        return InputConnection(this, true)
    }
}

class InputConnection internal constructor(val targetView: StarsPasswordView, fullEditor: Boolean) : BaseInputConnection(targetView, fullEditor) {

    override fun getEditable(): Editable {
        return targetView.passwordHolder
    }
    override fun commitText(text: CharSequence?, newCursorPosition: Int): Boolean {
        val res =  super.commitText(text, newCursorPosition)
        targetView.samsungWorkaround()
        return res
    }
}

当您想要设置

时会出现问题
 outAttrs.inputType = InputType.TYPE_CLASS_NUMBER

在这种情况下

  • InputConnection无法处理数字
  • getEditable()不会触发
  • commitText()不会触发

    所以我的解决方法只是处理setOnKeyListener中的麻木,如上所示。

有谁知道这是什么问题?

1 个答案:

答案 0 :(得分:2)

根据键盘的不同,并非所有密钥都通过InputConnection发送。有些是像硬键事件一样发送的,必须单独处理。这包括标准键盘上的数字键盘编号。就我目前所知,使用OnKeyListener就像你要做的那样(但请参阅@ pskink的评论here)。

您可以使用KeyEvent.getUnicodeChar()将文本字符与控制字符分开,如下所示。

if (keyEvent.getUnicodeChar() != 0) {
    // unicode text
    char unicodeChar = (char) keyEvent.getUnicodeChar();
} else {
    // control char
}

处理您需要的控制代码,但将捕获所有有效的Unicode字符(包括数字和新行(输入)字符)。

我在准备回答这个问题时写的问题和答案中更详细地介绍了这方面的一些方面。

我还更新了my previous answer关于接收键盘输入的自定义视图。