Thursday, January 29, 2009

How to have a tiled background ( cont.)

Thanks to Romain Guy, I finally could add a repeating background in my Android application !

I'm still using in my layout definition the same way to define the background, with a androidbackground parameter, with the path to your repeating background ( actually that was the point : having a consistent way for background, let them be tiled or not )

xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/MainLayout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="@drawable/backrepeat"
>
...

in my drawable directory, I have a back.png file (  the background I want to tile ), and I create this new backrepeat.xml file :
 <?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/back" 
    android:tileMode="repeat" />


Some points :
* I think my first tries failed because I forgot the 'xmlns:android' parameter.
* I tried without the xml version line, and it still works, but I think I will let it be there... Just in case !
* The tilemode can be repeat, mirror, or clamp.
* Although in Java, I could set a different repeat mode for X and Y, I don't think it is possible in the Xml file. Not that I really care for the moment :)

That's all !
Thanks again Romain ! 
I know it is your job, as a Android engineer, to evangelise and help us, but several times you really helped me, you were quick to answer, with concise and most useful answers...

Saturday, January 24, 2009

How to have a tiled background

Today, I wanted to have a tiled background in my activity.
Until now, my android application only had a stretched image, so I though it was a good time for a change !

Having a background pattern that repeat itself seems like a very common idea, in particular on mobile development where you do not want to spend too much memory on a big image !



But actually it took much more time that I would have think to find this one !
I finally came up with this code :



public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main_menu);
View MainLayoutView = (View) findViewById(R.id.MainLayout);
BitmapDrawable MyTiledBG = new BitmapDrawable( BitmapFactory.decodeResource(getResources(), R.drawable.background) );
MyTiledBG.setTileModeXY( Shader.TileMode.REPEAT , Shader.TileMode.REPEAT );
MainLayoutView.setBackgroundDrawable( MyTiledBG );
<...>
}
(note that you can use also Shader.TileMode.MIRROR to have a different repeatition pattern )

This code works fine, but I would have prefered a XML way to do this.

I've seen the BitmapDrawable attribute defined in the SDK, but couldn't come with anything working...

Tuesday, January 20, 2009

Sliding drawer, again

The sliding drawer developped by pskink has gone quite a long way from where it came from, and is now a really nice and, I think, usable widget, much like the google home page one !

This kind of widget is fun to use, and fits really well for mobile applications, where there is an obvious lack of place. And, on google phone, users are used with this widget, as there is one on the home page !

Here are some screen of this widget in action :



Enjoy !
[Edit ] :
Ooooppss...
I forget to add the link to the source :
You can find it here !
[/Edit]

Friday, January 16, 2009

Sliding Drawer

Interested in the Home Page sliding drawer ?

pskink has created a new widget like the google one.
Nice job, and easy to use...

Here it is :

Enjoy !

Wednesday, January 14, 2009

To accelerate or to decelerate ?

As many developers discovering a new development environment, I use and abuse of copy and paste.
Starting a new feature process is : 
  • finding in the documentation, or on the internet a similar feature, or something as close as possible, 
  • try to find the parameter/line / bit of code to change to have something like what I had in mind in the first time,
  • Be happy :)
  • ( if I have some time : fully understanding what I've just written... )

And most of the time, I don't have that much have time !

For my tries with animations, I find a sample that moved a view, copied this sample for making my high score list view slide out and in. And that's all.

Only now, I discover that in the sample animation I copied, there was this parameter :
android:interpolator="@android:anim/accelerate_interpolator"

And only now, I discover my mistake. The accelerator interpolator makes the speed of the moving view increase with the time.
So when my high score listview is sliding out of the screen, it has a slow speed at first, when one can see it in its integrality, and a fast speed at the end of the animation, when only a little part of it is visible.

But on the contrary, when it is sliding in in the screen, it has its greatest speed at the end of the animation, when one can see it in its integrality !
This just makes a awful animation !

Now that I discovered that my animation can decelerate for slides in, it is way better !


Wednesday, January 7, 2009

Chaining two animations, or how to repeat animationset...

Yesterday I tried to chain two animations !

Actually, what I wanted was, on my high-score list view : translate the listview out of the screen, change the listview content ( for a different type of game ), and retranslate the new listview in the screen.
But, reading the Android-dev mailing list, I realized that it could also interest people using an animationSet.
Apparently, a bug prevent them from handling the repeat flag correctly( see here )
(Note that in my case, I couldn't use an animationSet, because I want to have an operation between the two animations ).

So I first use a AnimationListener to detect the end of the first animation, and launch there the second animation, and...
Kaboum... it ... failed !!
I had discovered a second bug related to animation ( or at least an undocumented constraint ) : you can't launch an animation in the OnAnimationEnd method of the AnimationListener.
I guess after the OnAnimationEnd, there is something like a ClearAnimation done on the view, that remove both the old and the new ones !

So the solution here is to post a message to launch the second animation on the next trame.
So here's my solution :

public class ScorePage extends ListActivity
{
class LocalAnimationListener implements AnimationListener
{
public void onAnimationEnd(Animation animation)
{
//LaunchInAnimation( ); // FAIL:the animation is not launched
//runOnUiThread( mLaunchSecondAnimation ); // FAIL : the runnable is launched immediatly, so like previous method !
//Handler curHandler = new Handler(); // OK, BUT :
//curHandler.post( mLaunchSecondAnimation); // create an unnecessary object !
getListView().post(mLaunchSecondAnimation); // OK : GOOD method !
}
public void onAnimationRepeat(Animation animation)
{
}
public void onAnimationStart(Animation animation)
{
}
};
private Runnable mLaunchSecondAnimation = new Runnable()
{
public void run()
{
LaunchInAnimation();
}
};
LocalAnimationListener MyAnimationListener = new LocalAnimationListener();

public void LaunchInAnimation()
{
// Change the listView Content :
mCurrentHiScore -=1;
if ( mCurrentHiScore < 0 )
mCurrentHiScore = 2;
ListAdapter curAdapter = mScore.GetScoreListAdapter(ScorePage.this, R.layout.score_entry, mCurrentHiScore);
if ( curAdapter != null )
setListAdapter( curAdapter );

// Launch the second animation :
Animation SlideAnim;
SlideAnim = AnimationUtils.loadAnimation(this, R.anim.slide_in_left);
ListView lv = getListView();
lv.startAnimation(SlideAnim);
}

public void LaunchOutAnimation()
{
Animation SlideAnim;
SlideAnim = AnimationUtils.loadAnimation(this, R.anim.slide_out_left);
SlideAnim.setAnimationListener( MyAnimationListener );
ListView lv = getListView();
lv.startAnimation(SlideAnim);
}
(... )


Now it's just fine !

Sunday, January 4, 2009

A flashy widget: the sliding drawer

I recently found where the code for the sliding drawer was in the Android code.

So what is that sliding drawer ?
It is the panel containing your applications in Android Home page.
You know, the panel that you can drag up or down, and that was the first thing you played with when first testing Android emulator or the G1 !

Here's the code :
Sliding Drawer Code

I would like to have time to experiment with it ( ie copy/paste it, and use it in my own application ), but just reading the code is quite an inspiring experience ! I will try that as soon as possible...

This widget is nice and fun to use, give a good feeling to the user, make your application more profunssional, and is a very efficient way to spare space in the screen !

Just one thing : why on earth is the code hidden in the depth of Android source ?
Why isn't the widget available as a part of the API ?
I just can't understand it !

Android definitively misses some standard fun widgets.
Was it because of a lack of time ?
Will the sliding drawer appear in the next version ?
Will we find who killed the colonel Mustard ?

Friday, January 2, 2009

numeric editText and EditText with max number of characters... yes, again !

Sometimes, being a lone developer is a very depressing status.
You want a feature, you fight with the system, the tools, the documentations ( no comment ), the forums, ...
And you found a solution. So you're happy with all your code that do what you wanted.
Until you finally find you could achieve the same thing with only one line of code !

This is exactly what happened to me !
I found that a numeric editText ( or a textView) is done with this XML tag :
android:numeric="decimal"

Then I found that limiting the number of character is also very simple :
android:maxLength="10"


and that's all !


Why didn't I find that in the first time ( and spend so many time on my own solution ? ).
Because, I was looking at a way to do this by code.
And it is less obvious in code.
For the limited number of character, you can add a Android API filter :
InputFilter[] FilterArray = new InputFilter[1];
FilterArray[0] = new InputFilter.LengthFilter(8);
editEntryView.setFilters(FilterArray);


For the numeric editText, there is also a obscur solution :
DigitsKeyListener MyDigitKeyListener =
new DigitsKeyListener(true, true); // first true : is signed, second one : is decimal
editEntryView.setKeyListener( MyDigitKeyListener );


So all my work was useless ?
Possibly ( the politically correct answer is : oh no, I learned so many things in the process ), there is still a feature I have with my solution that is not 'that simple' with those solution, but I think I can do it also with implementing my own filter.
Now should I do it ? Filters look like they are no user friendly beasts, and my solution is already up and working !

Thursday, January 1, 2009

Happy New Year

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 !