2017-07-07 48 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