Widget de entrada de código PIN personalizado do Android
Eu estou tentando criar um widget de código PIN personalizado para android como uma alternativa para apenas usando umEditText
com um atributo inputType de senha. O que eu gostaria de exibir é uma linha de caixas, e cada caixa deve ser preenchida quando o usuário digita o pin dele.
Alguém fez algo assim, mas acabou por ser um número fixo deEditText
pontos de vista e havia um monte defeio código para troca de foco conforme os caracteres foram digitados ou excluídos. Esta não é a abordagem que quero seguir; em vez disso, estou projetando o meu para tercomprimento personalizável (fácil) e se comportar comovisão única focalizável (não tão fácil).
Meu conceito até agora é algum tipo de híbrido entre umLinearLayout
(para segurar as "caixas") e umEditText
(para armazenar a entrada do usuário).
Este é o código até agora ...
<code>public class PinCodeView extends LinearLayout { protected static final int MAX_PIN_LENGTH = 10; protected static final int MIN_PIN_LENGTH = 1; protected int pinLength; protected EditText mText; public PinCodeView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PinCodeView); try { pinLength = a.getInt(R.styleable.PinCodeView_pinLength, 0); } finally { a.recycle(); } pinLength = Math.min(pinLength, MAX_PIN_LENGTH); pinLength = Math.max(pinLength, MIN_PIN_LENGTH); setupViews(); Log.d(TAG, "PinCodeView initialized with pinLength = " + pinLength); } private void setupViews() { LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); for (int i = 0; i < pinLength; i++) { // inflate an ImageView and add it View child = inflater.inflate(R.layout.pin_box, null, false); addView(child); } } public CharSequence getText() { // TODO return pin code text instead return null; } public int length() { // TODO return length of typed pin instead return pinLength; } @Override public boolean onCheckIsTextEditor() { return true; } @Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { // TODO return an InputConnection return null; } } </code>
Sobre essas substituições:onCheckIsTextEditor () deve retornar true eonCreateInputConnection (EditorInfo outAttrs) deve retornar um novoInputConnection
objeto para interagir com um InputMethod (um teclado), mas isso é tudo que eu sei.
Alguém sabe se estou no caminho certo? Alguém já trabalhou comInputConnection
antes ou fizeram suas próprias visualizações editáveis capazes de dar orientação?
(Edit 1) Depois de olhar para isso um pouco mais, parece que eu deveria subclassificar BaseInputConnection e fornecer umaTextView
ouEditText
como seu alvo:
<code> @Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { if (!onCheckIsTextEditor()) { return null; } return new BaseInputConnection(mText, true); } </code>
Supondo que isso armazene o texto enquanto ele é digitado, ainda preciso de alguma maneira para atualizar as exibições para refletir a alteração de conteúdo ...
(Edit 2) Então, adicionei essa visualização personalizada a uma tela para teste. Ele mostra o número de caixas, e toda a visão é focável, mas o teclado nunca aparece. Eu sei que ganha / perde o foco porque as caixas mostram destaque de forma adequada e eu definir umOnFocusChangedListener
para gravar no logcat.
O que faz um teclado real aparecer quando uma visualização editável fica em foco?