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

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 !

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 !)

Monday, December 22, 2008

Solution for the traceview problem !

At last, a good samaritan (fadden, whoever you are, big thanks !! ) helps me find the solution for my traceview problem.

And actually, I can't imagine how he find it !
The data created by the Debug.startMethodTracing / Debug.stopMethodTracing pair only works when the debugger is NOT attached !

You can still launch it from Eclipse, but when the data file is created eclipse can't be used as a debugger ( though it still can be used as a way to get the log !).

I launched Eclipse, then my application ( so it started the emulator - with a -sdcard optional parameter ).
Then terminate my application with Eclipse.

At this point, I could use the android interface to launch my application, go to the part I wanted to profile, and generate a valid .trace file !!
I could get it from my emulated SD Card with the Eclipse DDMS perspective, and launch traceview with this file, and at last have a correct result (and quite interesting... More on that latter )

Thanks again fadden !


On a side note, one could be a little worried by a debugger that produce a different behaviour - in this case a different file - than the without debugger case.
For now, I will just close my eyes, and hope it is just in this case ( famous last words again ? )

Monday, December 15, 2008

TraceView : the Android profiler ?

Yesterday, I tried to use the Android profiler, traveView.

I carefully added a Debug.startMethodTracing("MyGame") and a Debug.stopMethodTracing() at the start and at the end of my activity, check that I had a file with a non zero length ( I hadn't that at the start ).

So I happily launch
traceview.bat c:\work\temp\MyGame.trace

How deceive I was to have such a result, instead of a nice graphic application !

Exception in thread "main" java.lang.RuntimeException: Method exit (java/lang/Object. ()V) does not match current method (java/lang/reflect/Constructor.constructNative ([Ljava/lang/Object;Ljava/lang/Class;[Ljava/lang/Class;IZ)Ljava/lang/Object;)
at com.google.traceview.ThreadData.exit(ThreadData.java:116)
at com.google.traceview.ThreadData.handleCall(ThreadData.java:78)
at com.google.traceview.DmTraceReader.parseDataPass2(DmTraceReader.java:285)
at com.google.traceview.DmTraceReader.parseData(DmTraceReader.java:176)
at com.google.traceview.DmTraceReader.generateTrees(DmTraceReader.java:78)
at com.google.traceview.DmTraceReader.(DmTraceReader.java:71)
at com.google.traceview.MainWindow.main(MainWindow.java:187)

I though it might be because of the path, so I put my trace file in my tool directory... Same results...

In the documentation, they don't use the .trace extension... With no hope I tried it... But it didn't change anything...

So for the moment, I have no solution.
On the forums, someone suggested that the profiler was simply not working on XP...
Well, I don't know.

if someone has a suggestion, I'd happily heard it !

Tuesday, December 9, 2008

How to deal with different Android Phone resolutions ?

Hi all, 


Now that Kogan will soon (?) release a new Phone ( Agora ), we should not limit our application to the T1 presets.

In peculiar, it looks like this phone will have a different resolution. It will be a QVGA one ( 320 x 240 pixels )  ( the T1 is 480x800).

The simplest way to deal with different resolution seems to handle different xml files for each resolution !

So we can have a res/layout-320x240 file and a res/layout-640x680 one, etc...

It let you have an acute control on your design, while still maintaining a common code.

Last note : it is not limited to layout, you can specify all of your resources, like drawable !




Friday, December 5, 2008

Issues with ListViews, at last solved !!

Hi all, 

At least after trying all the android parameters, I found the correct one to fix my issue !

It was the cacheColorHint, that was to be set to #00000000 !

I tried this :


android:textColorPrimary="#FF112233"
android:textColorPrimaryDisableOnly="#FF112233"
android:textColorPrimaryInverse="#FF112233"
android:textColorPrimaryInverseNoDisable="#FF112233"
android:textColorPrimaryNoDisable="#FF112233"
android:textColorSecondary="#FF112233"
android:textColorSecondaryInverse="#FF112233"
android:textColorSecondaryInverseNoDisable="#FF112233"
android:textColorSecondaryNoDisable="#FF112233"
android:textColorTertiary="#FF112233"
android:textColorTertiaryInverse="#FF112233"
android:listSelector="@android:color/transparent"
android:drawSelectorOnTop="false"

that failed miserably, and this single line just saved my day :


android:cacheColorHint="#00000000"

Ok, good to know...
I just feel like the documentation was a little light on this subject.
There are so many parameters, and this one does not look like the more intuitive to change for my problem.

Ok, that's done, that will be enough for today !

Wednesday, December 3, 2008

problem with a ListView


I am stuck with a aesthetic issue with List Views for several days, and I can't find any solution.

So, as a very experimented programmer as I am, I'm gonna use a very advanced technique : ask for any solution for this problem publicaly !
Usually, some seconds after warning the whole planet, the programmer finds the solution on his own !


Here's my problem :
I have a ListActivity, with my list of High Scores :


Score List on My Android Phone

But the problem arises when I click on the listView to make it scroll :

Google Android Phone Emulator View

It is less sexy this way ( and also quite less readable ).

I tried to juggle with some parameters, like enable / clickable / focusable / focusableInTouchMode (that I just understood from the http://android-developers.blogspot.com/ site). I also tried the listSelector or the background parameters ; but with no success...

I'm sure there is something I miss there, but what...


( Note : I have now found the solution here )




Sunday, November 9, 2008

EditText with limited number of characters

I just fough with the SDK for quite some time to find this one.

As a average modern programer, I started by looking on the internet, but didn't find anything. I imagine I didn't search the right sites ( no comments on this please ! )

So this is what I came up with :


editEntryView.setOnKeyListener
(
new View.OnKeyListener()
{
public boolean onKey(View v, int keyCode, KeyEvent event)
{
EditText NameView = (EditText ) editEntryView.findViewById( R.id.PlayerName );
String Name = NameView.getText().toString();
if ( Name.length() >= 8 )
{
if ( keyCode != KeyEvent.KEYCODE_DEL )
return true;
}
return false;
}
}
);

I imagine that there are many things that should be cleaner here, but, hey !, it works, and that so good for me !

I fought for some time, because I was looking for a way to call a parent method when I didn't treat the case and decided to pass for this letter.
Actually, the behaviour is just the opposite :
if you return true, it means you dealed with the entry, so the treatment will stop here.
if you return false, it means you didn't deal with the entry, so it will be passed to the next listener.

Actually, a classic listener pattern !



Next thing : enter as a ok-click entry !

Saturday, November 8, 2008

List with custom or no separator

My achievement today ( OK, it's just a small one )

I wanted to have no separator in my list activity...

After some moment parsing all the documentation in every possible way, here what I found :

public class ScorePage extends ListActivity
{

Score mScore;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle)
{
super.onCreate(icicle);

this.getListView().setDivider( null );
this.getListView().setDividerHeight(0);
}


By the way, is the DividerHeight set necessary ?
I added it because of a very stressful comment on the SetDivider method...

(One test later )

It is by no way necessary !!
But I find that adding a non zero height was what I was wanting for, ie adding a blank space between two entries !


Next step tomorrow !

Starting point

This is the first message...

As usual ( ? ), it doesn't have any purpose, but essentially to verify that the text I'm writing right now will appear somewhere on the Internet !

So I will just introduce myself :
I'm a (professional) game developer, so quite an expert of C++ trickery, essentially on Xbox360 and PS3 ( though I also worked on Wii, PS2 and GC ), and, obviously, on PC.

This is the diary of the creation, in my spare time ( essentially my nights, when wife and kids are sleeping ), of a casual game on Google Android phones !

I'm discovering java, the mobile world, eclipse, and the Google world !