Widget de entrada de código pin personalizado de Android

Estoy tratando de crear un widget de código pin personalizado para Android como alternativa a solo usar unEditText con una contraseña inputType atributo. Lo que me gustaría mostrar es una fila de cuadros, y que cada cuadro se llene a medida que el usuario escribe su pin.

Alguien más hizo algo como esto, pero resultó ser un número fijo deEditText Vistas y hubo un montón defeo Código para cambiar el foco a medida que se escriben o eliminan los caracteres. Este NO es el enfoque que quiero tomar; más bien, estoy diseñando la mía para tenerlongitud personalizable (fácil) y comportarse como unvista enfocable única (No tan fácil).

Mi concepto hasta ahora es algún tipo de híbrido entre unLinearLayout (para mantener las "cajas") y unaEditText (para almacenar la entrada del usuario).

Este es el código hasta ahora ...

<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 esas anulaciones:onCheckIsTextEditor () debe devolver verdadero yonCreateInputConnection (EditorInfo outAttrs) debe devolver un nuevoInputConnection objeto para interactuar con un InputMethod (un teclado), pero eso es todo lo que sé.

¿Alguien sabe si estoy en el camino correcto? ¿Alguien ha hecho trabajo conInputConnection Antes o hizo sus propios puntos de vista editables capaces de dar orientación?

(Editar 1) Después de ver esto un poco más, parece que debería subclase BaseInputConnection y suministrar unaTextView oEditText como su objetivo:

<code>    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        if (!onCheckIsTextEditor()) {
            return null;
        }
        return new BaseInputConnection(mText, true);
    }
</code>

Suponiendo que esto almacena el texto a medida que se escribe, todavía necesito alguna forma de actualizar las vistas para reflejar el cambio de contenido ...

(Edición 2) Así que agregué esta vista personalizada a una pantalla para probar. Muestra el número de cuadros, y la vista completa se puede enfocar, pero el teclado nunca aparece. Sé que gana / pierde el enfoque porque las casillas se muestran resaltando apropiadamente y establezco unaOnFocusChangedListener escribir en logcat.

¿Qué hace que aparezca un teclado real cuando se enfoca una vista editable?

Respuestas a la pregunta(4)

Su respuesta a la pregunta