Thursday, December 25, 2008

EditText, Sligh return !

First of all, merry Christmas to everyone !!!

That's said, let's get back to the EditText.

I've written a blog entry on how to make a EditText with a limited number of characters ( there )
It works by intercepting the key pressed event, and deciding whether to use the new entered letter or not.
It's all good and working, but I read on the forum that that was not the best of the solutions !
Actually, it's intercepting the physical keyboard entry at the view level, and it is not right. The most important thing is : when the software keyboard is out, it won't work anymore...
So I restarted to work on it, and used a the 'addTextChangedListener' listener, in order to detect when the text was changed, whoever had changed it.
This sound much more right.
So I started with something like that :

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


That was a good start.
But there is still a issue with this code :
If I reach the character limit, and execute the NameView.SetText code, it puts the caret before the first character of the entry !
Imagine you're writing your name in this edit text, and suddenly, some characters disappear, and you're now typing at the start of your Name.

Not a very good experience !

I had to change that !
So i decided to replace the caret, just where it was before the change :
There is not such a thing as a caret, in the Android world, but there is a selection, and it looks like it's ok for what I want.
Here is what I came up with :

public void onTextChanged(CharSequence s, int start, int before, int count)
{
if( s.length() > 8 )
{
EditText NameView = (EditText ) editEntryView.findViewById( R.id.PlayerName );
int currentCarretPos = NameView.getSelectionStart();
String TextContent = NameView.getText().toString();
if ( TextContent.length() > 8 )
{
TextContent = TextContent.substring(0, 8 );
NameView.setText(TextContent);
if ( currentCarretPos > 8 )
currentCarretPos = 8;
NameView.setSelection( currentCarretPos );
}
}
}


Much better.
In a "normal" 'I'm entering my name' utilization, it works just fine !
I'm still not completely sure it is the way to go, in peculiar, when too much letters are entered from the middle of the word.
But it's enough for tonight( 3 AM looks like a good time to stop !)

No comments: