I wish you all a very happy new year, with a lot of happy Android ( or other ) programming !
Full of activities of any sorts ( poor pun intended )!
I plan to ship my first Android program as soon as possible (this month would be great), and to continue explaining issues and solutions found here !
2009 should be the year of the Android explosion, with several new phones coming...
It will definitively be an interesting year for an android developer !
A blog from an Android developer.
Developing since the start of the platform, and constantly improving my applications, I share my experience developping with Google OS for smartphones.
Thursday, January 1, 2009
Wednesday, December 31, 2008
listView with background
hello,
I had some questions about my issue with listView (here).
So I will make it clear :
When you use a listView with a background, you must use
Not to have any display problem !
I had some questions about my issue with listView (here).
So I will make it clear :
When you use a listView with a background, you must use
android:cacheColorHint="#00000000"
Not to have any display problem !
Sunday, December 28, 2008
Numeric only editText
Based on what we have done yesterday (here ), it's very easy to limit our EditText to whatever we want !
And a common application would be to implement a numeric only editText :
Here's a first int version :
editEntryView.addTextChangedListener
(
new TextWatcher()
{
String CurrentWord;
private boolean IsValid( CharSequence s )
{
for ( int i = 0; i < s.length(); i ++ )
{
if ( !Character.isDigit( s.charAt(i)))
return false;
}
return true;
}
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( !IsValid(s) )
{
editEntryView.setText(CurrentWord);
editEntryView.setSelection( start );
}
}
}
);
That simple !
And if you want any decimal numeric, just write another IsValid method :
private boolean IsValid( CharSequence s )
{
// special autorization for empty field
if (s.length() == 0)
return true;
// special autorization for '.', in order to enter .5
if (s.length() == 1 && s.charAt(0) == '.')
return true;
try
{
Double.parseDouble( s.toString() );
return true;
}
catch( Exception e)
{
return false;
}
}
We just have to be careful for special cases like the empty field, or just a dot ( this is the needed transition to enter something like .5 ).
And we must take into account those special cases when we will validate the entry.
And a common application would be to implement a numeric only editText :
Here's a first int version :
editEntryView.addTextChangedListener
(
new TextWatcher()
{
String CurrentWord;
private boolean IsValid( CharSequence s )
{
for ( int i = 0; i < s.length(); i ++ )
{
if ( !Character.isDigit( s.charAt(i)))
return false;
}
return true;
}
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( !IsValid(s) )
{
editEntryView.setText(CurrentWord);
editEntryView.setSelection( start );
}
}
}
);
That simple !
And if you want any decimal numeric, just write another IsValid method :
private boolean IsValid( CharSequence s )
{
// special autorization for empty field
if (s.length() == 0)
return true;
// special autorization for '.', in order to enter .5
if (s.length() == 1 && s.charAt(0) == '.')
return true;
try
{
Double.parseDouble( s.toString() );
return true;
}
catch( Exception e)
{
return false;
}
}
We just have to be careful for special cases like the empty field, or just a dot ( this is the needed transition to enter something like .5 ).
And we must take into account those special cases when we will validate the entry.
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 !
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 !
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 !)
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 !)
Subscribe to:
Posts (Atom)