2017-07-07 47 views
1

我做了我的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) 
        [email protected] true 
       if (keyCode == KeyEvent.KEYCODE_BACK) 
        [email protected] 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()) 
         } 
        } 
       [email protected] 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没有按't处理数字
  • getEditable()不会触发
  • commitText()不会触发

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

有谁知道这个问题是什么?

回答

1

根据键盘,并非所有的键都通过InputConnection发送。有些发送像硬键事件,必须分开处理。这包括标准键盘上的数字键盘编号。据我目前的了解,像你一样使用OnKeyListener是要走的路(但请参阅@ pskink的评论here)。

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

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

处理你所需要的控制代码,但所有有效的Unicode字符(包括数字和新线(输入)字符)会被抓住。

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

我也更新my previous answer有关接收键盘输入自定义视图。

+0

我得到的一个大问题是键盘事件在三星手机上没有捕捉到。你遇到过这个问题吗? – Gorets

+0

@戈雷茨,我还没有遇到这个问题,但我没有三星手机来测试它。那很糟。所以数字,删除和输入不起作用?请尽快通知我们解决方案。我也会更多地考虑这一点。 – Suragch

+0

这是否描述你的问题? https://stackoverflow.com/questions/4282214/onkeylistener-not-working-on-virtual-keyboard – Suragch