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:
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.
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).