Android EditText cursor wrong position

1.2k views Asked by At

I try to set comma format in EditText. It works perfectly when I try to enter from 1-9. But if the EditText has some text and the cursor is not at the end, and I try to enter 1-9 it will not in order 1-9, the cursor will place incorrect position. The text should be "91,234,567,899"

See the images bellow.

How to fix it?

Correct Incorrect

This is how android calculator worked:

Android Calculator

Below is my code :

1.activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    tools:context="com.example.user.test.MainActivity">

    <EditText
        android:id="@+id/et_number"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#fff"
        android:imeOptions="actionDone"
        android:inputType="numberDecimal"
        android:maxLines="1"
        android:maxLength="30"
        android:textColor="#000"
        android:textSize="17sp"
        android:textStyle="bold"
        android:singleLine="true"
        android:paddingLeft="20dp"
        android:digits="0123456789.,"/>
</LinearLayout>

2.MainActivity.java

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    final EditText editText = (EditText) findViewById(R.id.et_number);
    editText.addTextChangedListener(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) {

        }

        @Override
        public void afterTextChanged(Editable s) {
            String value = s.toString();
            editText.removeTextChangedListener(this);
            s.replace(0, value.length(), getDecimalFormattedString(value));
            editText.addTextChangedListener(this);
        }
    });
}

String history;
public String getDecimalFormattedString(String value) {
    try {
        value = value.replaceAll("," , "");
        int dot_amt = 0;
        for (int i = 0; i < value.length(); i++){
            if ('.' == value.charAt(i)){
                dot_amt++;
            }
        }
        if (dot_amt > 1){
            return history;
        }else {
            String str1 = value;
            String str2 = "";
            if (value.contains(".")){
                str1 = value.substring(0, value.indexOf("."));
                if ("".equals(str1)){
                    str1 = "0";
                }
                str2 = value.substring(value.indexOf("."), value.length());
                if (str2.length() > 2){
                    str2 = str2.substring(0, 3);
                }
            }
            str1 = String.valueOf(Long.parseLong(str1));
            String str3 = "";
            int i = 0;
            for (int k = str1.length()-1; k >= 0 ; k--) {
                if (i == 3) {
                    str3 = "," + str3;
                    i = 0;
                }
                str3 = str1.charAt(k) + str3;
                i++;
            }
            history = str3+str2;
        }
        return history;
    }catch (Exception e){
        e.printStackTrace();
    }
    return "";
}
}
1

There are 1 answers

6
JavaNoob On BEST ANSWER

Just change your code like, the main idea is setSelection(originSelection++) after you insert a ',' into original value

        @Override
        public void afterTextChanged(Editable s) {
            String value = s.toString();
            editText.removeTextChangedListener(this);
            String fixedValue = getDecimalFormattedString(value);
            int preSelection = editText.getSelectionEnd();
            s.replace(0, value.length(), fixedValue);
            editText.setSelection(preSelection + fixedValue.length() - value.length());
            editText.addTextChangedListener(this);
        }

and a simple implement of getDecimalFormattedString, this is an option

 public String getDecimalFormattedString(String value) {

    final int lastIndex = value.length() - 1;

    if (!value.contains(".")) {
        value = value.replaceAll(",", "");
        StringBuilder builder = new StringBuilder(value);
        String reverseStr = builder.reverse().toString();
        int commaCount = 0;
        for (int i = 1; i < reverseStr.length(); i++) {
            if (i % 3 == 0) {
                builder.insert(commaCount + i, ",");
                commaCount++;
            }
        }
        value = builder.reverse().toString();
        history = value;//forgot it 
    } else if (value.charAt(lastIndex) == '.' && value.indexOf('.') != lastIndex) {
        value = history;
    }

    return value;
}

that's it, wish it could help you!