Niestandardowy widżet wprowadzania kodu PIN w systemie Android

Próbuję utworzyć niestandardowy widget kodu PIN dla Androida jako alternatywę dla zwykłego używaniaEditText z atrybutem inputType hasła. Chciałbym wyświetlić rząd pudełek i zapełnić każde pudełko, gdy użytkownik wpisze swój pin.

Ktoś inny zrobił coś takiego, ale okazało się, że jest to stała liczbaEditText widoki i było ich dużobrzydki kod do zamiany fokusa, gdy znaki zostały wpisane lub usunięte. To NIE jest podejście, które chcę przyjąć; raczej projektuję moje, które mamkonfigurowalna długość (łatwe) i zachowuj się jakwidok pojedynczej ostrości (nie tak łatwo).

Moja dotychczasowa koncepcja to rodzaj hybrydy między aLinearLayout (trzymać „pola”) iEditText (aby zapisać dane wejściowe użytkownika).

To jest kod do tej pory ...

<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>

O tych zmianach:onCheckIsTextEditor () powinien zwrócić true ionCreateInputConnection (OutAttrs edytora informacji) powinien zwrócić nowyInputConnection obiekt do interakcji z InputMethod (klawiatura), ale to wszystko, co wiem.

Czy ktoś wie, czy jestem na dobrej drodze? Czy ktoś zrobił z tym pracęInputConnection wcześniej lub tworzyli własne edytowalne widoki, które mogą dać wskazówki?

(Edytuj 1) Po obejrzeniu tego więcej, wydaje mi się, że powinienem podklasować BaseInputConnection i supply aTextView lubEditText jako cel:

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

Zakładając, że to przechowuje tekst w takiej postaci, w jakiej został wpisany, nadal potrzebuję sposobu, aby zaktualizować widoki, aby odzwierciedlić zmianę treści ...

(Edytuj 2) Dodałem więc ten niestandardowy widok do ekranu do testowania. Pokazuje liczbę skrzynek, a cały widok jest nastawialny, ale klawiatura nigdy nie pojawia się. Wiem, że zyskuje / traci ostrość, ponieważ pola pokazują odpowiednio podświetlenie i ustawiamOnFocusChangedListener pisać do logcata.

Co sprawia, że ​​rzeczywista klawiatura pojawia się, gdy widok edytowalny jest aktywny?

questionAnswers(4)

yourAnswerToTheQuestion