Редактировать текст для OTP с каждой буквой в отдельных позициях

Привет, я работаю над приложением, которое запрашивает OTP, когда пользователь хочет сбросить свой пароль, для которого мне нужен текст, такой как тот, что на прилагаемом изображении... Что я подумал, чтобы продолжить, это отдельный текст для каждого письма, Все из них расположены в линейном расположении горизонтальной ориентации с некоторым запасом... и максимальной длиной как 1, так что в каждый текст редактирования может быть введена только одна буква... Это правильный подход? Какие-либо предложения??

enter image description here

Ответы

Ответ 1

Вы можете попробовать это, сделав TextWatcher более универсальным, чтобы его было легко использовать и понимать

Используйте ниже класс:

public class GenericTextWatcher implements TextWatcher
    {
        private View view;
        private GenericTextWatcher(View view) 
        {
            this.view = view;
        }

        @Override
        public void afterTextChanged(Editable editable) {
            // TODO Auto-generated method stub
            String text = editable.toString();
            switch(view.getId())
            {

            case R.id.editText1:
                if(text.length()==1)
                    et2.requestFocus(); 
                break;
            case R.id.editText2:
                if(text.length()==1)
                    et3.requestFocus();
                else if(text.length()==0)
                    et1.requestFocus();  
                break;
            case R.id.editText3:
                if(text.length()==1)
                    et4.requestFocus();
                else if(text.length()==0)
                    et2.requestFocus();
                break;
            case R.id.editText4:
                if(text.length()==0)
                    et3.requestFocus();
                break;
            }
        }

        @Override
        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
            // TODO Auto-generated method stub
        }

        @Override
        public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
            // TODO Auto-generated method stub
        }
    }

Как использовать выше класс

et1.addTextChangedListener(new GenericTextWatcher(et1));
et2.addTextChangedListener(new GenericTextWatcher(et2));
et3.addTextChangedListener(new GenericTextWatcher(et3));
et4.addTextChangedListener(new GenericTextWatcher(et4));

Здесь et1, et2, et3 и et4 - ваши EditTexts, я знаю его соглашение о недопустимом наименовании в соответствии со стандартом Java, но вы можете заменить его своим.

PS Вы можете найти дизайн XML для этого здесь GitHub, некоторые другие, пример дизайна XML для справки.

Ответ 2

enter image description here

Я реализовал следующий код на основе других ответов.

Я хотел, чтобы этот код был очень простым, оптимизированным и понятным для изменений.

Не используйте android:maxLength="1" в вашем xml.

//package your package

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;

public class PinActivity extends AppCompatActivity {

    private EditText editText1, editText2, editText3, editText4;
    private EditText[] editTexts;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pin);

        editText1 = (EditText) findViewById(R.id.otpEdit1);
        editText2 = (EditText) findViewById(R.id.otpEdit2);
        editText3 = (EditText) findViewById(R.id.otpEdit3);
        editText4 = (EditText) findViewById(R.id.otpEdit4);
        editTexts = new EditText[]{editText1, editText2, editText3, editText4};

        editText1.addTextChangedListener(new PinTextWatcher(0));
        editText2.addTextChangedListener(new PinTextWatcher(1));
        editText3.addTextChangedListener(new PinTextWatcher(2));
        editText4.addTextChangedListener(new PinTextWatcher(3));

        editText1.setOnKeyListener(new PinOnKeyListener(0));
        editText2.setOnKeyListener(new PinOnKeyListener(1));
        editText3.setOnKeyListener(new PinOnKeyListener(2));
        editText4.setOnKeyListener(new PinOnKeyListener(3));
    }


    public class PinTextWatcher implements TextWatcher {

        private int currentIndex;
        private boolean isFirst = false, isLast = false;
        private String newTypedString = "";

        PinTextWatcher(int currentIndex) {
            this.currentIndex = currentIndex;

            if (currentIndex == 0)
                this.isFirst = true;
            else if (currentIndex == editTexts.length - 1)
                this.isLast = true;
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            newTypedString = s.subSequence(start, start + count).toString().trim();
        }

        @Override
        public void afterTextChanged(Editable s) {

            String text = newTypedString;

            /* Detect paste event and set first char */
            if (text.length() > 1)
                text = String.valueOf(text.charAt(0)); // TODO: We can fill out other EditTexts

            editTexts[currentIndex].removeTextChangedListener(this);
            editTexts[currentIndex].setText(text);
            editTexts[currentIndex].setSelection(text.length());
            editTexts[currentIndex].addTextChangedListener(this);

            if (text.length() == 1)
                moveToNext();
            else if (text.length() == 0)
                moveToPrevious();
        }

        private void moveToNext() {
            if (!isLast)
                editTexts[currentIndex + 1].requestFocus();

            if (isAllEditTextsFilled() && isLast) { // isLast is optional
                editTexts[currentIndex].clearFocus();
                hideKeyboard();
            }
        }

        private void moveToPrevious() {
            if (!isFirst)
                editTexts[currentIndex - 1].requestFocus();
        }

        private boolean isAllEditTextsFilled() {
            for (EditText editText : editTexts)
                if (editText.getText().toString().trim().length() == 0)
                    return false;
            return true;
        }

        private void hideKeyboard() {
            if (getCurrentFocus() != null) {
                InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
                inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
            }
        }

    }

    public class PinOnKeyListener implements View.OnKeyListener {

        private int currentIndex;

        PinOnKeyListener(int currentIndex) {
            this.currentIndex = currentIndex;
        }

        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_DEL && event.getAction() == KeyEvent.ACTION_DOWN) {
                if (editTexts[currentIndex].getText().toString().isEmpty() && currentIndex != 0)
                    editTexts[currentIndex - 1].requestFocus();
            }
            return false;
        }

    }

}

Ответ 3

Используйте 4 разных EditText.Используйте приведенный ниже код, чтобы изменить фокус после последующей записи.

private EditText editText1;
private EditText editText2;
private EditText editText3;
private EditText editText4;

    editText1.addTextChangedListener(new TextWatcher() {

            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (editText1.getText().toString().length() == 1)     //size as per your requirement
                {
                    editText2.requestFocus();
                }
            }

            public void beforeTextChanged(CharSequence s, int start,
                                          int count, int after) {
            }

            public void afterTextChanged(Editable s) {
            }

        });

    editText2.addTextChangedListener(new TextWatcher() {

            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (editText2.getText().toString().length() == 1)     //size as per your requirement
                {
                    editText3.requestFocus();
                }
            }

            public void beforeTextChanged(CharSequence s, int start,
                                          int count, int after) {
            }

            public void afterTextChanged(Editable s) {
            }

        });

и так далее...

Соедините текст со всем EditText.

Ответ 4

я сделал общий TextWatcher для 6-значный OTP:

public class GenericTextWatcher implements TextWatcher {
        private View view;

        GenericTextWatcher(View view) {
            this.view = view;
        }

        @Override
        public void afterTextChanged(Editable s) {
            boolean allOtherFilled = false;
            EditText nextEdit = null;
            EditText previousEdit = null;
            switch (view.getId()) {
                case R.id.otp_et1:
                    allOtherFilled = otpEdit2.getText().length() == 1
                            && otpEdit3.getText().length() == 1
                            && otpEdit4.getText().length() == 1
                            && otpEdit5.getText().length() == 1
                            && otpEdit6.getText().length() == 1;
                    nextEdit = otpEdit2;
                    break;
                case R.id.otp_et2:
                    allOtherFilled = otpEdit1.getText().length() == 1
                            && otpEdit3.getText().length() == 1
                            && otpEdit4.getText().length() == 1
                            && otpEdit5.getText().length() == 1
                            && otpEdit6.getText().length() == 1;
                    nextEdit = otpEdit3;
                    previousEdit = otpEdit1;
                    break;
                case R.id.otp_et3:
                    allOtherFilled = otpEdit1.getText().length() == 1
                            && otpEdit2.getText().length() == 1
                            && otpEdit4.getText().length() == 1
                            && otpEdit5.getText().length() == 1
                            && otpEdit6.getText().length() == 1;
                    nextEdit = otpEdit4;
                    previousEdit = otpEdit2;
                    break;
                case R.id.otp_et4:
                    allOtherFilled = otpEdit1.getText().length() == 1
                            && otpEdit2.getText().length() == 1
                            && otpEdit3.getText().length() == 1
                            && otpEdit5.getText().length() == 1
                            && otpEdit6.getText().length() == 1;
                    nextEdit = otpEdit5;
                    previousEdit = otpEdit3;
                    break;
                case R.id.otp_et5:
                    allOtherFilled = otpEdit1.getText().length() == 1
                            && otpEdit2.getText().length() == 1
                            && otpEdit3.getText().length() == 1
                            && otpEdit4.getText().length() == 1
                            && otpEdit6.getText().length() == 1;
                    nextEdit = otpEdit6;
                    previousEdit = otpEdit4;
                    break;
                case R.id.otp_et6:
                    allOtherFilled = otpEdit1.getText().length() == 1
                            && otpEdit2.getText().length() == 1
                            && otpEdit3.getText().length() == 1
                            && otpEdit4.getText().length() == 1
                            && otpEdit5.getText().length() == 1;
                    previousEdit = otpEdit5;
                    break;
            }

            if (s.length() == 1) {
                if (allOtherFilled) {
                    //if next 2 edit texts are filled , enable the pay button
                    enableDisableButton(continueButton, true);
                    KeyboardUtils.hideKeyboard(LoginActivity.this, (EditText) view);
                }
            } else if (s.length() > 1) {
                if (allOtherFilled) {
                    //if all next edit texts are filled , enable the pay button
                    enableDisableButton(continueButton, true);
                    KeyboardUtils.hideKeyboard(LoginActivity.this, (EditText) view);

                } else if (nextEdit != null) {
                    if (nextEdit.getText().length() == 0) {
                        //if next edit is not filled, move to next edit and set the second digit
                        moveToNextEdit(nextEdit, (EditText) view);
                    } else {
                        //if any other edit is not filled, stay in current edit
                        enableDisableButton(continueButton, false);
                        stayOnCurrentEdit((EditText) view);
                    }
                }
            } else if (s.length() < 1) {
                if (null != previousEdit)
                    moveToPreviousEdit(previousEdit);
                enableDisableButton(continueButton, false);
            }
        }

        @Override
        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
        }

        @Override
        public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
        }

        private void stayOnCurrentEdit(EditText editText) {
            editText.setText(editText.getText().toString().substring(0, 1));
            editText.setSelection(editText.getText().length());
        }

        private void moveToPreviousEdit(EditText editText) {
            editText.setSelection(editText.getText().length());
            editText.requestFocus();
        }

        private void moveToNextEdit(EditText editText2, EditText editText1) {
            editText2.setText(editText1.getText().toString().substring(1, 2));
            editText2.requestFocus();
            editText2.setSelection(editText2.getText().length());
            editText1.setText(editText1.getText().toString().substring(0, 1));
        }
    }

Вы можете добавить этот textWatcher ко всем вашим текстам редактирования следующим образом:

this.otpEdit1.addTextChangedListener(new GenericTextWatcher(otpEdit1));

Ответ 5

Приведенное ниже решение учитывает:

  1. Автоматическая фокусировка на следующий текст редактирования при вводе одной цифры OTP в фокусном тексте редактирования.

  2. Автоматическая фокусировка на предыдущий текст редактирования при удалении одной цифры OTP в текстовом редакторе с фокусом.

Комбинация работы в onTextChanged() и afterTextChanged() помогает в достижении того же.

private EditText firstDigitOtpEdt, secondDigitOtpEdt, thirdDigitOtpEdt, fourthDigitOtpEdt;

firstDigitOtpEdt.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        @Override
        public void afterTextChanged(Editable editable) {
            if (firstDigitOtpEdt.getText().toString().length() == 1) {
                secondDigitOtpEdt.requestFocus();
            }
        }
    });

secondDigitOtpEdt.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            if (secondDigitOtpEdt.getText().toString().length() == 0) {
                firstDigitOtpEdt.requestFocus();
            }
        }

        @Override
        public void afterTextChanged(Editable editable) {
            if (secondDigitOtpEdt.getText().toString().length() == 1) {
                thirdDigitOtpEdt.requestFocus();
            }
        }
    });

thirdDigitOtpEdt.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            if (thirdDigitOtpEdt.getText().toString().length() == 0) {
                secondDigitOtpEdt.requestFocus();
            }
        }

        @Override
        public void afterTextChanged(Editable editable) {
            if (thirdDigitOtpEdt.getText().toString().length() == 1) {
                fourthDigitOtpEdt.requestFocus();
            }
        }
    });

fourthDigitOtpEdt.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            if (fourthDigitOtpEdt.getText().toString().length() == 0) {
                thirdDigitOtpEdt.requestFocus();
            }
        }

        @Override
        public void afterTextChanged(Editable editable) {
           // We can call api to verify the OTP here or on an explicit button click
        }
    });

Ответ 6

Вы можете попробовать это, если хотите добавить дополнительную логику для удаления OTP, я создаю его на основе ответа от AR, убедитесь, что вы установили maxlength = 2 для всех edittext

public class GenericTextWatcher implements TextWatcher
{
    private View view;
    private GenericTextWatcher(View view)
    {
        this.view = view;
    }
    @Override
    public void afterTextChanged(Editable editable) {
        // TODO Auto-generated method stub
        String text = editable.toString();
        switch (view.getId()) {

            case R.id.etOTP1:
                if (text.length() > 1) {
                    etOTP1.setText(String.valueOf(text.charAt(0)));
                    etOTP2.setText(String.valueOf(text.charAt(1)));
                    etOTP2.requestFocus();
                    etOTP2.setSelection(etOTP2.getText().length());
                }
                break;
            case R.id.etOTP2:
                if (text.length() > 1){
                    etOTP2.setText(String.valueOf(text.charAt(0)));
                    etOTP3.setText(String.valueOf(text.charAt(1)));
                    etOTP3.requestFocus();
                    etOTP3.setSelection(etOTP3.getText().length());
                }
                if (text.length() == 0){
                    etOTP1.requestFocus();
                    etOTP1.setSelection(etOTP1.getText().length());
                }
                break;
            case R.id.etOTP3:
                if (text.length() > 1){
                    etOTP3.setText(String.valueOf(text.charAt(0)));
                    etOTP4.setText(String.valueOf(text.charAt(1)));
                    etOTP4.requestFocus();
                    etOTP4.setSelection(etOTP4.getText().length());
                }
                if (text.length() == 0){
                    etOTP2.requestFocus();
                    etOTP2.setSelection(etOTP2.getText().length());
                }
                break;
            case R.id.etOTP4:
                if (text.length() == 0){
                    etOTP3.requestFocus();
                    etOTP3.setSelection(etOTP3.getText().length());
                }
                break;
        }
    }
    @Override
    public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
    }

    @Override
    public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
    }
}

Ответ 7

используя DataBinding:

class EnterOTPDialogFragment extends Fragment {
    FragmentEnterOtpdialogBinding binding;
    GenericTextWatcher watcher1;
    GenericTextWatcher watcher2;
    GenericTextWatcher watcher3;
    GenericTextWatcher watcher4;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_enter_otpdialog, container, false);

        watcher1 = new GenericTextWatcher(binding.optDigit1);
        watcher2 = new GenericTextWatcher(binding.optDigit2);
        watcher3 = new GenericTextWatcher(binding.optDigit3);
        watcher4 = new GenericTextWatcher(binding.optDigit4);
        binding.optDigit1.addTextChangedListener(watcher1);
        binding.optDigit1.setOnKeyListener(watcher1);
        binding.optDigit2.addTextChangedListener(watcher2);
        binding.optDigit2.setOnKeyListener(watcher2);
        binding.optDigit3.addTextChangedListener(watcher3);
        binding.optDigit3.setOnKeyListener(watcher3);
        binding.optDigit4.addTextChangedListener(watcher4);
        binding.optDigit4.setOnKeyListener(watcher4);
        return binding.getRoot();
    }

    public class GenericTextWatcher implements TextWatcher, View.OnKeyListener {
        private View view;
        String previousText = "";

        private GenericTextWatcher(View view) {
            this.view = view;
        }

        @Override
        public void afterTextChanged(Editable editable) {
            // TODO Auto-generated method stub
            String text = editable.toString();
            switch (view.getId()) {

                case R.id.optDigit1:
                    if (text.length() == 1) {
                        if (previousText.length() > 0) {
                            binding.optDigit1.removeTextChangedListener(watcher1);
                            binding.optDigit1.setText(previousText);
                            binding.optDigit1.addTextChangedListener(watcher1);

                            binding.optDigit2.removeTextChangedListener(watcher2);
                            binding.optDigit2.setText(text);
                            binding.optDigit2.addTextChangedListener(watcher2);
                        }
                        binding.optDigit2.requestFocus();
                    }
                    break;
                case R.id.optDigit2:
                    if (text.length() == 1) {
                        if (previousText.length() > 0) {
                            binding.optDigit2.removeTextChangedListener(watcher2);
                            binding.optDigit2.setText(previousText);
                            binding.optDigit2.addTextChangedListener(watcher2);

                            binding.optDigit3.removeTextChangedListener(watcher3);
                            binding.optDigit3.setText(text);
                            binding.optDigit3.addTextChangedListener(watcher3);

                        }
                        binding.optDigit3.requestFocus();

                    } else if (text.length() == 0)
                        binding.optDigit1.requestFocus();
                    break;
                case R.id.optDigit3:
                    if (text.length() == 1) {
                        if (previousText.length() > 0) {
                            binding.optDigit3.removeTextChangedListener(watcher3);
                            binding.optDigit3.setText(previousText);
                            binding.optDigit3.addTextChangedListener(watcher3);

                            binding.optDigit4.removeTextChangedListener(watcher4);
                            binding.optDigit4.setText(text);
                            binding.optDigit4.addTextChangedListener(watcher4);
                        }
                        binding.optDigit4.requestFocus();
                    } else if (text.length() == 0)
                        binding.optDigit2.requestFocus();
                    break;
                case R.id.optDigit4:
                    if (text.length() == 0) {

                        binding.optDigit3.requestFocus();
                    } else {
                        try {
                            final InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
                            imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
                            Log.e(TAG, "afterTextChanged: hide keyboard");
                        } catch (Exception e) {
                            Log.e(TAG, "afterTextChanged: " + e.toString());
                        }
                    }


                    break;
            }
        }

        @Override
        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
            // TODO Auto-generated method stub
            Log.d(TAG, "beforeTextChanged: " + arg0);
            if (arg0.length() > 0) {
                previousText = arg0.toString();
            }
        }

        @Override
        public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
            // TODO Auto-generated method stub
        }

        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            previousText = "";
            Log.d(TAG, "onKey: keyCode = " + keyCode + ", event = " + event.toString());
            if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KEYCODE_DEL) {
                switch (view.getId()) {
                    case R.id.optDigit2:
                        if (binding.optDigit2.getText().toString().trim().length() == 0)
                            binding.optDigit1.requestFocus();
                        break;
                    case R.id.optDigit3:
                        if (binding.optDigit3.getText().toString().trim().length() == 0)
                            binding.optDigit2.requestFocus();
                        break;
                    case R.id.optDigit4:
                        if (binding.optDigit4.getText().toString().trim().length() == 0)
                            binding.optDigit3.requestFocus();
                        else if (binding.optDigit4.getText().toString().trim().length() == 1)
                            try {

                                ((BaseActivity) getActivity()).hideSoftKeyboard();
                            } catch (Exception e) {
                                Log.e(TAG, "afterTextChanged: " + e.toString());
                            }
                        break;
                }

            }
            return false;
        }
    }
}

Ответ 8

Вы можете создать собственный редактор Editext и добавить его в свой XML файл, найти ниже пользовательский класс

public class CustomEntryEdittext extends LinearLayout { 

    public int entryCount = 0; //count of boxes to be created
    private int currentIndex = 0;
    private static int EDITTEXT_MAX_LENGTH = 1; //character size of each editext
    private static int EDITTEXT_WIDTH = 40;
    private static int EDITTEXT_TEXTSIZE = 20; //textsize
    private boolean disableTextWatcher = false, backKeySet = false;
    private TextWatcher txtWatcher;
    private onFinishListerner mListerner;


    public CustomEntryEdittext(Context context) {
        super(context, null);
    }

    public CustomEntryEdittext(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomEntryEdittext(Context context, AttributeSet attrs, int defStyle) {
        this(context, attrs, defStyle, 0);
    }

    public CustomEntryEdittext(Context context, AttributeSet attrs, int defStyle, int defStyleRes) {
        super(context, attrs);
        init(context, attrs);
    }

    public void setOnFinishListerner(onFinishListerner listerner) {
        this.mListerner = listerner;
    }

    public interface onFinishListerner {
        void onFinish(String enteredText);
    }


    private void init(Context context, AttributeSet attrs) {

        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.CustomEntryEdittext, 0, 0);


        entryCount = a.getInteger(R.styleable.CustomEntryEdittext_editextCount, 0);

        a.recycle();

        setOrientation(LinearLayout.HORIZONTAL);
        setGravity(Gravity.CENTER_VERTICAL);

        for (int i = 0; i < entryCount; i++) {

            //creates edittext based on the no. of count
            addView(initialiseAndAddChildInLayout(i, context), i);
        }

    }

    //method focuses of previous editext
    private void getPreviousEditext(int index) {
        if (index > 0) {
            EditText edtxt = (EditText) getChildAt(index - 1);
            disableTextWatcher = true;

             edtxt.setText("");
            edtxt.requestFocus();
            disableTextWatcher = false;

        }
    }

    //method focuses of previous editext
    private void getPreviousEditextFocus(int index) {
        if (index > 0) {
            EditText edtxt = (EditText) getChildAt(index - 1);
            disableTextWatcher = true;
            edtxt.requestFocus();
            disableTextWatcher = false;
        }
    }


    //method to focus on next edittext
    private void getNextEditext(int index) {
        if (index < entryCount - 1) {
            EditText edtxt = (EditText) getChildAt(index + 1);
            edtxt.requestFocus();
        }
    }


    private View initialiseAndAddChildInLayout(int index, Context context) {
        final EditText editext = new EditText(context);
        editext.setMaxWidth(1);
        editext.setTag(index);
        editext.setGravity(Gravity.CENTER);
        editext.setTextSize(EDITTEXT_TEXTSIZE);
        editext.setInputType(EditorInfo.TYPE_CLASS_NUMBER);
        editext.setFilters(new InputFilter[]{new InputFilter.LengthFilter(EDITTEXT_MAX_LENGTH)});
        LayoutParams param = new LayoutParams(0, LayoutParams.WRAP_CONTENT, 1);
        editext.setLayoutParams(param);
        editext.addTextChangedListener(txtWatcher = new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {


            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                currentIndex = Integer.parseInt(editext.getTag().toString());


                if (editext.getText().toString().length() == 1 && !disableTextWatcher) {
                    getNextEditext(currentIndex);
                } else if (editext.getText().toString().length() == 0 && !disableTextWatcher) {// && !isFirstTimeGetFocused && !backKeySet) {
                    getPreviousEditext(currentIndex);
                }

            }

            @Override
            public void afterTextChanged(Editable s) {


            }
        });
        editext.setOnKeyListener(new OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (keyCode == KeyEvent.KEYCODE_DEL) {
                    currentIndex = Integer.parseInt(editext.getTag().toString());
                    if (editext.getText().toString().length() == 0 && !disableTextWatcher) {
                        getPreviousEditextFocus(currentIndex);
                    } else {
                        disableTextWatcher = true;
                        editext.setText("");
                        disableTextWatcher = false;
                    }
                    backKeySet = true;
                }

                return true;
            }


        });
        editext.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_DONE)) {
                    if(currentIndex==entryCount-1 && getEnteredText().length()==entryCount)
                    {
                        mListerner.onFinish(getEnteredText());
                    }
                }
                return false;
            }
        });

        return editext;
    }


    public String getEnteredText() {
        String strEnteredValue = "";
        for (int i = 0; i < getChildCount(); i++) {
            EditText editText = (EditText) getChildAt(i);
            if (editText.getText() != null && editText.getText().toString().length() > 0)
                strEnteredValue = strEnteredValue + editText.getText().toString();

        }
        return strEnteredValue;
    }

    public void clearCustomEntryEdittext() {
        for (int i = 0; i < getChildCount(); i++) {
            EditText editText = (EditText) getChildAt(i);
            editText.setText("");
        }
        EditText editText = (EditText) getChildAt(0);
        editText.requestFocus();
    }
}

//and add it in your xml file

<com.custom.widget.CustomEntryEdittext
android:id="@+id/custom_unique_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerInParent="true"
app:editextCount="6″>
</com.custom.widget.CustomEntryEdittext>

Для справки ниже ссылки

https://madoverandroid.wordpress.com/2017/07/11/edittext-with-separate-box-for-each-letter-customentryedittext/

Ответ 9

Вы можете создать подкласс TextWatcher и реализовать собственную логику.

public class OTPTextWatcher implements TextWatcher {

private EditText view;
    private List<EditText> otpDigitViews;
    private OTPListener otpListener;

    public OTPTextWatcher(EditText otpView, List<EditText> otpDigitViews, OTPListener listener) {
        view = otpView;
        this.otpDigitViews = otpDigitViews;
        this.otpListener = listener;
    }


    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

    }

    @Override
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

    }

    @Override
    public void afterTextChanged(Editable editable) {

        String digit1 = otpDigitViews.get(0).getText().toString();
        String digit2 = otpDigitViews.get(1).getText().toString();
        String digit3 = otpDigitViews.get(2).getText().toString();
        String digit4 = otpDigitViews.get(3).getText().toString();
        String currentDigit = editable.toString();
        final String inputValue = digit1 + digit2 + digit3 + digit4;

        if (inputValue.length() == 4) {
            if (inputValue.equals("1234")) {
                otpListener.onOTPSuccess();
            } else {
                otpListener.onOTPError();
            }
        } else {
            if (currentDigit.length() >= 1
                    && view != otpDigitViews.get(3)) {
                if (view != null)
                    view.focusSearch(View.FOCUS_RIGHT).requestFocus();
            } else {
                if (currentDigit.length() <= 0 && view.getSelectionStart() <= 0) {
                    try {
                        view.focusSearch(View.FOCUS_LEFT).requestFocus();
                    } catch (NullPointerException e) {
                        LogHelper.printErrorLog("There is not view left to current edit text");
                    }
                }
            }
        }
    }

    public interface OTPListener {
        void onOTPSuccess();

        void onOTPError();
    }
}

Ответ 10

используя макет DataBinding:

public class EnterOTPActivity extends AppCompatActivity {
            private ActivityEnterOtpBinding binding;
            private Context mContext;
            private int currentEditIndex;


            @Override
            protected void onCreate(@Nullable Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                binding = DataBindingUtil.setContentView(this, R.layout.activity_enter_otp);
                mContext = this;

                binding.et1.addTextChangedListener(new MyTextChangeWatcher(1));
                binding.et2.addTextChangedListener(new MyTextChangeWatcher(2));
                binding.et3.addTextChangedListener(new MyTextChangeWatcher(3));
                binding.et4.addTextChangedListener(new MyTextChangeWatcher(4));
                binding.et5.addTextChangedListener(new MyTextChangeWatcher(5));
                binding.et6.addTextChangedListener(new MyTextChangeWatcher(6));

                binding.et1.setOnKeyListener(keyListener);
                binding.et2.setOnKeyListener(keyListener);
                binding.et3.setOnKeyListener(keyListener);
                binding.et4.setOnKeyListener(keyListener);
                binding.et5.setOnKeyListener(keyListener);
                binding.et6.setOnKeyListener(keyListener);


            }

            private View.OnKeyListener keyListener = new View.OnKeyListener() {

                @Override
                public boolean onKey(View v, int keyCode, KeyEvent event) {

                    if ((((EditText) v).getText().toString() == null || ((EditText) v)
                            .getText().toString().isEmpty())
                            && keyCode == KeyEvent.KEYCODE_DEL
                            && event.getAction() == KeyEvent.ACTION_DOWN) {

                        if (currentEditIndex == 6)
                            currentEditIndex = 5;
                        if (currentEditIndex > 0) {
                            EditText editText = getEditTextFromIndex(currentEditIndex);
                           editText.setText("");
                            editText.requestFocusFromTouch();
                            currentEditIndex--;
                        }
                    }

                    return false;
                }
            };

            class MyTextChangeWatcher implements TextWatcher {
                private int index;

                public MyTextChangeWatcher(int index) {
                    super();
                    this.index = index;
                }

                @Override
                public void afterTextChanged(Editable s) {
                    if (s != null && s.length() == 1) {
                        if (index < 7) {

                            if (index < 6) {
                                EditText editText = getEditTextFromIndex(index);
                                editText.clearFocus();
                                getEditTextFromIndex(index + 1).requestFocusFromTouch();
                            }
                            currentEditIndex = index;
                        } else {

                        }
                    } else {
                    }
                }

                @Override
                public void beforeTextChanged(CharSequence s, int start, int count,
                                              int after) {
                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before,
                                          int count) {
                }
            }

            private EditText getEditTextFromIndex(int index) {
                switch (index) {
                    case 1:
                        return binding.et1;
                    case 2:
                        return binding.et2;
                    case 3:
                        return binding.et3;
                    case 4:
                        return binding.et4;
                    case 5:
                        return binding.et5;
                    case 6:
                        return binding.et6;

                    default:
                        break;
                }
                return null;
            }
        }

Ответ 11

public class GenericTextWatcher implements TextWatcher {
    private EditText etPrev;
    private EditText etNext;

    public GenericTextWatcher(EditText etNext, EditText etPrev) {
        this.etPrev = etPrev;
        this.etNext = etNext;
    }

    @Override
    public void afterTextChanged(Editable editable) {
        String text = editable.toString();
        if (text.length() == 1)
            etNext.requestFocus();
        else if (text.length() == 0)
            etPrev.requestFocus();
    }

    @Override
    public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
    }

    @Override
    public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
    }
}

Затем мы добавляем addTextChangedListener в каждый текст редактирования.

e1.addTextChangedListener(GenericTextWatcher(e2, e1))
e2.addTextChangedListener(GenericTextWatcher(e3, e1))
e3.addTextChangedListener(GenericTextWatcher(e4, e2))
e4.addTextChangedListener(GenericTextWatcher(e5, e3))
e5.addTextChangedListener(GenericTextWatcher(e6, e4))
e6.addTextChangedListener(GenericTextWatcher(e6, e5))

Ответ 12

Вот некоторые из ссылок, которые могут помочь. Вы можете настроить его согласно вашему требованию.

Эта ссылка представляет собой пошаговое руководство по созданию собственного пользовательского интерфейса ввода вывода. https://medium.com/@ali.muzaffar/building-a-pinentryedittext-in-android-5f2eddcae5d3#.ldp03yky7

PinEntry android Library https://github.com/Philio/PinEntryView