Пользовательский виджет ввода пин-кода Android

Я пытаюсь создать собственный виджет пин-кода для Android в качестве альтернативы простому использованию EditTextс атрибут inputType пароля. То, что я хотел бы отобразить, - это ряд полей, и каждое поле должно быть заполнено, когда пользователь вводит свой пин-код.

Кто-то еще делал что-то подобное, но получилось фиксированное количество EditTextпредставлений и было много уродливогокода для переключения фокуса при вводе или удалении символов . Это НЕ тот подход, который я хочу использовать; скорее, я разрабатываю свой так, чтобы он имел настраиваемую длину(легко) и вел себя как одно фокусируемое представление(не так просто).

До сих пор моя концепция представляла собой своего рода гибрид между LinearLayout(для хранения «коробок») и EditText(для хранения пользовательского ввода).

Пока это код...

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

Об этих переопределениях: onCheckIsTextEditor()должен возвращать true и onCreateInputConnection(EditorInfo outAttrs)должен возвращать новый InputConnectionдля взаимодействия с InputMethod (клавиатурой), но это все, что я знаю.

Кто-нибудь знает, на правильном ли я пути? Кто-нибудь работал с InputConnectionраньше или делал свои собственные редактируемые представления, способные давать рекомендации?

(Редактировать 1) Посмотрев на это еще немного, кажется, что я должен подклассировать BaseInputConnection и указать TextView или EditText в качестве цели:

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

Предполагая, что это сохраняет текст в том виде, в котором он напечатан, все еще нужен какой-то способ обновить представления, чтобы отразить изменение содержимого...

(Редактировать 2) Поэтому я добавил этот пользовательский вид на экран для тестирования. Он показывает количество полей, и весь вид можно сфокусировать, но клавиатура никогда не появляется.Я знаю, что он получает/теряет фокус, потому что поля правильно подсвечены, и я установил OnFocusChangedListenerдля записи в logcat.

Из-за чего появляется реальная клавиатура, когда редактируемый вид получает фокус?

5
задан Robert Harvey 6 August 2012 в 19:08
поделиться