Saturday, December 27, 2008

EditView with limited number of character, the end ?

I was still not completely OK with the last version.
In particular, when reaching the number of character limit while entering letters in the middle of the word, the behavior was not really natural : the new letter is added and the last letter of the words are erased !

So I had to find something better !

As I was entering the TextWatcher realm, I felt I could use it more to reach my goal : I want that reaching the character limit prevent any new character to be entered !

the new solution : saving the word before it is altered, then restoring the saved word if it is not Ok after being changed.

Here we go:

editEntryView.addTextChangedListener
(
new TextWatcher()
{
String CurrentWord;
public void afterTextChanged(Editable s)
{
}
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
CurrentWord = s.toString();
}
public void onTextChanged(CharSequence s, int start, int before, int count)
{
if( s.length() > MAX_CHAR )
{
EditText NameView = (EditText ) editEntryView.findViewById( R.id.PlayerName );
NameView.setText(CurrentWord);
}
}
}
);



This is good, the behaviour is OK, but... there is still a 'but' :
I don't replace the caret at the proper place. I could do the same trick I did last time : get the previous caret pos before the setText, and set it after, but this is still wrong : in this case, the caret place will take into account the rejected letter, so it will be moved one letter on the right.
I could still set the caret at the last pos minus one. But what will happen when there is a copy and paste feature ( does it already exist ? ), and several letters have been added at the same time ?

The solution seems cleaner, and is simpler : I use the start parameter given to the onTextChanged method. This parameter tells us the place where the word has been changed : this is the place I want to put the caret back.
So here's my final version, and I think I completely happy with it :

editEntryView.addTextChangedListener
(
new TextWatcher()
{
String CurrentWord;
public void afterTextChanged(Editable s)
{
}
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
CurrentWord = s.toString();
}
public void onTextChanged(CharSequence s, int start, int before, int count)
{
if( s.length() > MAX_CHAR )
{
editEntryView.setText(CurrentWord);
editEntryView.setSelection( start );
}
}
}
);

Enjoy !

2 comments:

Digital Spaghetti said...

Hey,

Thanks for this, this is exactly what I was looking for!

AndroidBlogger said...

Thank you !
It's always nice to hear I could help someone !

Note :
If you just want to limit the number of characters, have you seen this :
http://androidblogger.blogspot.com/2009/01/numeric-edittext-and-edittext-with-max.html

This version is much more simpler !
(ie already implemented in android... )