Estoy tratando de crear un widget de código PIN personalizado para Android como alternativa a simplemente usar un EditText
con un atributo de entrada de tipo de contraseña. Lo que me gustaría mostrar es una fila de recuadros, y que cada recuadro se llene a medida que el usuario escribe su pin.Widget personalizado de entrada de código PIN de Android
que otro había hecho algo como esto, pero resultó ser un número fijo de EditText
vistas y había una gran cantidad de código fea para el bombeo de enfoque como personajes fueron mecanografiados o eliminados. Este NO es el enfoque que quiero tomar; más bien, estoy diseñando el mío para tener longitud personalizable (fácil) y comportarme como vista individualizable (no tan fácil).
Mi concepto hasta ahora es algún tipo de híbrido entre un LinearLayout
(para contener las "cajas") y un EditText
(para almacenar la entrada del usuario).
Este es el código hasta ahora ...
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;
}
}
Sobre esas anulaciones: onCheckIsTextEditor() debe devolver verdadero y onCreateInputConnection(EditorInfo outAttrs) debe devolver una nueva InputConnection
objeto de interactuar con un InputMethod (un teclado), pero eso es todo lo saber.
¿Alguien sabe si estoy en el camino correcto? ¿Alguien ha trabajado anteriormente con InputConnection
o ha creado sus propias vistas editables para orientar?
(Edit 1) Después de mirar esta un poco más, parece que debería subclase BaseInputConnection y suministrar una TextView
o EditText
como su objetivo:
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
if (!onCheckIsTextEditor()) {
return null;
}
return new BaseInputConnection(mText, true);
}
Suponiendo que esta no almacenar el texto tal y como se escribe, Todavía necesito alguna forma de actualizar las vistas para reflejar el cambio de contenido ...
(Editar 2) Así que agregué esta vista personalizada a una pantalla para probar. Muestra el número de cuadros, y toda la vista es enfocable, pero el teclado nunca aparece. Sé que gana/pierde el foco porque los recuadros muestran el resaltado de manera apropiada y configuré un OnFocusChangedListener
para escribir en logcat.
¿Qué hace que un teclado real aparezca cuando se enfoca una vista editable?
Si se siente generoso, sería genial si este código se hiciera disponible en github. ¡Gracias por publicar! – saranicole
Realmente me gustaría, pero está en uso en la aplicación de mi compañía, por lo que no sé si puedo liberar el código fuente para ello. Déjame verlo con mi gerente. – Karakuri
¿Alguna actualización sobre cómo liberar esto en github o si alguien más hizo tal progreso? El código que se muestra aquí parece realmente prometedor y un buen punto de partida para otros, aunque realmente apreciaría el paquete total. Tal vez Android lo implemente eventualmente como otro tipo de campo :) –