Skip to content
Advertisement

As a user starts to type in an EditText can it append a file extension to the end?

Problem: I’ve been trying unsuccessfully to append a file extension which follows the cursor in real-time as a user types.

What I’ve tried: I’ve been trying to use the .addTextChangedListener() which I think is correct, but having an issue trying to make the idea happen. Debugging shows is continually looping and so it gives the appearance of freezing. I looked at a couple post here on the forum but the ones suggested when I entered this post title dealt with prefixes and not suffixes.

EditText field with highlighted area representing text to follow right of cursor:

EditText

One of my poor attempts to make it work:

private void setupAddDBEditText(){

    mDBToAdd.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) {
            if(s.toString().contains(".db"))
                mDBToAdd.setText(s.toString().substring(0,s.toString().length()-3));
            mDBToAdd.setText(s + ".db");
        }
}

Advertisement

Answer

You will need to remove the listener when you change the text (that’s why you are getting an infinite loop).

You can make a custom TextWatcher to handle this sort of thing (below) that removes itself as a watcher, changes the text and puts the cursor in the right place, then adds itself back.

public class FileExtensionTextWatcher implements TextWatcher {
    private final String extension;
    private final EditText text;

    FileExtensionTextWatcher(EditText t, String ext) {
        extension = ext;
        text = t;
    }

    // you may want to change around the logic in here to allow for
    // odd entries or other changes - but the overall approach should
    // be similar
    private String removeAutoExtension(String s) {
        String ext = "." + extension;
        if( s.contains(ext) ) {
            int ei = s.lastIndexOf(ext);
            if( ei == 0 ) return "";
            String trailingChar = "";
            if( ei < s.length() - ext.length() ) {
                trailingChar = s.substring(ei+ext.length());
            }
            return s.substring(0,ei) + trailingChar;
        }
        else {
            return s;
        }
    }

    @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 txt) {
        if( txt == null ) return;

        String currentText = txt.toString();
        String filename = removeAutoExtension(currentText);
        int initCursor = filename.length();
        String displayedText;
        if( filename.isEmpty() ) {
            displayedText = filename;
        }
        else {
            displayedText = filename + "." + extension;
        }

        text.removeTextChangedListener(this);
        txt.clear();
        txt.insert(0, displayedText);
        text.setSelection(initCursor);
        text.addTextChangedListener(this);
    }
}

You would then use it like this

EditText e = findViewById(R.id.edit_text);
e.addTextChangedListener(new FileExtensionTextWatcher(e, "db"));

Here is a demo GIF of how it looks.

demo GIF

There are some changes you may want to make to handle things like whether the user is allowed to enter their own extension (this form does not allow it – but you could change that with some extra logic in the custom watcher).

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement