Пользовательский виджет ввода пин-кода Android
Я пытаюсь создать пользовательский виджет пин-кода для Android в качестве альтернативы просто использовать EditText
с атрибутом ввода пароля типа. То, что я хотел бы отобразить, это ряд ящиков, и каждый из них должен быть заполнен, когда пользователь вводит свой пин-код.
Кто-то сделал что-то подобное, но оказалось, что это фиксированное число 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.
Что заставляет настоящую клавиатуру появляться, когда редактируемый вид фокусируется?
4 ответа
Я добился значительного прогресса в этом и больше не нуждаюсь в помощи с InputConnection. Короче говоря, вы продлеваете BaseInputConnection
и переопределить getEditable()
вернуть редактируемый. В этом случае я возвращаю личное TextView
используется внутри PinCodeView
, PinCodeView
также переопределяет несколько методов, таких как onKey[foo]()
и переадресация вызова на внутренний TextView
, Остальное просто с помощью TextWatcher
обновить одного из детей ImageView
s всякий раз, когда текст изменяется.
Это работает очень хорошо. Осталось еще несколько незначительных проблем, чтобы исправить это, но я рассмотрю их как отдельные вопросы и закрою здесь.
Похоже, вы пытаетесь создать iOS-вид, похожий на запись с пин-кодом.
Вот хороший пример кода, который вы можете найти полезным. Тем не менее, это фиксированная длина, но все же может быть полезно для некоторых людей.
https://github.com/chinloong/Android-PinView
http://madeveloper.blogspot.com/2013/02/android-ios-like-pin-entrychallenge.html
Я знаю, что на это уже ответили, но так как его реализация не передана, я нашел похожую библиотеку с открытым исходным кодом Это выглядит хорошо и для всех тех, кто бродит может попробовать
Выглядит нормально для меня. Что-то, что вы можете сделать, это когда пользователь вводит символ в один EditText
найти ссылку на следующее поле EditText и сделать requestFocus()
в теме. Это переместит текстовую запись в следующее поле. Очень просто.
implementation 'com.alimuzaffar.lib:pinentryedittext:1.3.10'
Поместите эту зависимость в файл Gradle вашего модуля приложения и выполните синхронизацию.
<com.alimuzaffar.lib.pin.PinEntryEditText
android:inputType="number"
android:id="@+id/Pin_Et"
android:maxLength="6"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
Поместите этот код в XML (файл макета).
Он отлично работает, я использую этот код