0

I have three EditText Boxes, that has the following requirements: -

  • Should not allow User Touch and should be navigated only using the 'Enter Key' and the Backspace buttons.
  • Each Edit Texts can have 2 characters, once filled up, it should automatically focus to the next EditText box on right (View.FOCUS_RIGHT) (currently I am using TextWatcher to detect this).

  • If the User presses backspaces and the current EditText box is empty, the focus should be moved to the previous EditText box (View.FOCUS_LEFT).

  • If the current EditText has Maximum characters (2), and the user keys in a new character, the focus should be shifted to the next (right) EditText and the newly entered character should be inserted into the newly focused EditText.

Here is the code that I have:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.multitiext.mutlitextviewapp.MainActivity">

<TextView
    android:id="@+id/tv_text_display"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World!" />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:layout_alignParentStart="true"
    android:layout_below="@+id/tv_text_display"
    android:layout_marginTop="40dp"
    android:orientation="horizontal">

    <com.multitiext.mutlitextviewapp.custom.MyEditText
        android:id="@+id/et_input01"
        android:layout_width="60dp"
        android:layout_height="match_parent"
        android:inputType="textCapWords"
        android:imeOptions="actionNext"
        android:maxLength="@integer/max_length_per_edit_text"
        android:selectAllOnFocus="true"/>

    <com.multitiext.mutlitextviewapp.custom.MyEditText
        android:id="@+id/et_input02"
        android:layout_width="60dp"
        android:layout_height="match_parent"
        android:inputType="textCapWords"
        android:imeOptions="actionNext"
        android:maxLength="@integer/max_length_per_edit_text"
        android:selectAllOnFocus="true" />

    <com.multitiext.mutlitextviewapp.custom.MyEditText
        android:id="@+id/et_input03"
        android:layout_width="60dp"
        android:layout_height="match_parent"
        android:inputType="textCapWords"
        android:imeOptions="actionDone"
        android:maxLength="@integer/max_length_per_edit_text"
        android:selectAllOnFocus="true" />
</LinearLayout>


</RelativeLayout>`

Here is my Activity with the Three EditText fields:

`public class MainActivity extends AppCompatActivity {

private MyEditText et_input01;
private MyEditText et_input02;
private MyEditText et_input03;
private TextView tv_display01;
private String fullText;

private View nextET = null;
private EditText currentET = null;
private Integer maxLengthPerEditText;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initUI();
    setInitialFocus();
    setListeners();
    showSoftKeyboard();
}

private void initUI() {
    et_input01 = (MyEditText) findViewById(R.id.et_input01);
    et_input02 = (MyEditText) findViewById(R.id.et_input02);
    et_input03 = (MyEditText) findViewById(R.id.et_input03);
    et_input01.setCurrentET(et_input01);
    et_input02.setCurrentET(et_input02);
    et_input03.setCurrentET(et_input03);
    tv_display01 = (TextView) findViewById(R.id.tv_text_display);
    maxLengthPerEditText = getResources().getInteger(R.integer.max_length_per_edit_text);
}

private void setListeners() {
    InputFilter[] inputFilters = new InputFilter[] {new InputFilter.AllCaps()
    };
    et_input01.setFilters(inputFilters);
    et_input02.setFilters(inputFilters);
    et_input03.setFilters(inputFilters);

    Log.i(MainActivity.class.getName(), "Adding listeners");
    et_input03.setOnEditorActionListener(new TextView.OnEditorActionListener() {
        @Override
        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
            if (actionId == EditorInfo.IME_ACTION_DONE) {
                fullText = (new StringBuilder(et_input01.getText().toString()))
                        .append(et_input02.getText().toString())
                        .append(et_input03.getText().toString())
                        .toString();
                tv_display01.setText(fullText);
            }
            if (event.getKeyCode()==KeyEvent.ACTION_UP && event.getAction() == KeyEvent.KEYCODE_DEL){
                et_input02.requestFocus();
            }
            return false;
        }
    });

    et_input02.setOnEditorActionListener(new TextView.OnEditorActionListener() {
        @Override
        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
            if (event.getKeyCode()==KeyEvent.ACTION_UP && event.getAction() == KeyEvent.KEYCODE_DEL) {
                et_input01.requestFocus();
            }
            return false;
        }
    });


    et_input01.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            nextET = null;
            currentET = et_input01;
        }
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

        }
        @Override
        public void afterTextChanged(Editable s) {
            Log.i("MainActivity", "et01: " + s.toString());
            String currentText = s.toString();
            int currentTextLength = currentText.length();
            String newText = "";
            String moveToNextString = "";

            if (currentTextLength == maxLengthPerEditText) {
                nextET = currentET.focusSearch(View.FOCUS_RIGHT);
            }
            if (currentTextLength == 0) {
            }
            if (currentTextLength > maxLengthPerEditText) {
                newText = (currentText).substring(0, maxLengthPerEditText);
                moveToNextString = (currentText).substring(maxLengthPerEditText);
                currentET.setText(newText);
                nextET = currentET.focusSearch(View.FOCUS_RIGHT);
                if (nextET != null && nextET instanceof EditText) {
                    ((EditText) nextET).setText(moveToNextString);
                }
            }
            if (nextET != null && nextET instanceof EditText) {
                nextET.requestFocus();
            }
        }
    });

    et_input02.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            nextET = null;
            currentET = et_input02;
        }
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

        }
        @Override
        public void afterTextChanged(Editable s) {
            Log.i("MainActivity", "et02: " + s.toString());
            String currentText = s.toString();
            int currentTextLength = currentText.length();
            String newText = "";
            String moveToNextString = "";

            if (currentTextLength == maxLengthPerEditText) {
                nextET = currentET.focusSearch(View.FOCUS_RIGHT);
            }
            if (currentTextLength == 0) {
                nextET = currentET.focusSearch(View.FOCUS_LEFT);
            }
            if (currentTextLength > maxLengthPerEditText) {
                newText = (currentText).substring(0, maxLengthPerEditText);
                moveToNextString = (currentText).substring(maxLengthPerEditText);
                currentET.setText(newText);
                nextET = currentET.focusSearch(View.FOCUS_RIGHT);
                if (nextET != null && nextET instanceof EditText) {
                    ((EditText) nextET).setText(moveToNextString);
                }
            }
            if (nextET != null && nextET instanceof EditText) {
                nextET.requestFocus();
            }
        }
    });

    et_input03.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            nextET = null;
            currentET = et_input03;
        }
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

        }
        @Override
        public void afterTextChanged(Editable s) {
            Log.i("MainActivity", "et03: " + s.toString());
            String currentText = s.toString();
            int currentTextLength = currentText.length();
            String newText = "";

            if (currentTextLength == maxLengthPerEditText) {
            }
            if (currentTextLength == 0) {
                nextET = currentET.focusSearch(View.FOCUS_LEFT);
            }
            if (currentTextLength > maxLengthPerEditText) {
                newText = (currentText).substring(0, maxLengthPerEditText);
                currentET.setText(newText);
            }
            if (nextET != null && nextET instanceof EditText) {
                nextET.requestFocus();
            }
        }
    });
}

private void setInitialFocus() {
    et_input01.requestFocus();
}

private void showSoftKeyboard() {
    InputMethodManager imm = (InputMethodManager) getSystemService(getApplicationContext().INPUT_METHOD_SERVICE);
    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED,0);
}

}`

I have a customized EditText to detect backspace, but it currently cannot be used to move to the previous EditText field, if the current field is empty (From an answer here: Android EditText delete(backspace) key event).

public class MyEditText extends EditText {

private MyEditText currentET;

public MyEditText(Context context, AttributeSet attrs) {
    super(context, attrs);

}

public MyEditText(Context context) {
    super(context);

}

public MyEditText(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);

}

public void setCurrentET(MyEditText currentET) {
    this.currentET = currentET;
}

@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
    return new MyInputConnection(super.onCreateInputConnection(outAttrs),
            true);
}

private class MyInputConnection extends InputConnectionWrapper {

    public MyInputConnection(InputConnection target, boolean mutable) {
        super(target, mutable);
    }

    @Override
    public boolean sendKeyEvent(KeyEvent event) {

        return super.sendKeyEvent(event);
    }

    @Override
    public boolean deleteSurroundingText(int beforeLength, int afterLength) {
        if (beforeLength == 1 && afterLength == 0) {
            return sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
        }
        return super.deleteSurroundingText(beforeLength, afterLength);
    }
}

}`

The issues that I am currently seeing are: - if the EditText is empty and if the Backspace is pressed, the previous EditText is not selected. - Is there a much simpler way to achieve the requirements here?

Community
  • 1
  • 1
Dinesh Kumar
  • 307
  • 1
  • 3
  • 9
  • Depending on the exact use case this could potentially not a be a very good idea from a design-perspective. Changing the default behavior of keys in an EditText could prove to be confusing to a users expectation of how things "should" work. Behaving as expected is an important part of good design – camlunt Mar 28 '16 at 18:09
  • @camlunt well, I am trying to ease the movement between the text boxes for the user by doing so. The user wont have to manually select the text boxes after completing etc. That is the requirement btw. – Dinesh Kumar Mar 29 '16 at 01:12

0 Answers0