I’ve recently updated the GreenDroid library (available on GitHub). Here is a list of the main changes:

  • Improvements to the ActionBar
  • New “applying” system
  • Bugs fixed

Improvements to the ActionBar

With the first release of GD[Tab|List]Activity it wasn’t possible to create “non regular” items. This release introduces ActionBarItem. An ActionBarItem is an object representing a single action button in the ActionBar. It may act differently depending on its purpose. For instance, a LoaderActionBarItem switches from a regular button to a circular ProgressBar once pressed. A NormalActionBarItem displays a simple Drawable.

/*
 * This will add a "refresh" button that switches from button with two rounded arrows
 * to an indeterminate ProgressBar
 */
addActionBarItem(Type.Refresh);

To prevent developers from designing icons, GreenDroid also includes several base items … (Refresh, Export, Locate, etc.). Do not hesitate to use it as it makes ActionBar development easier and increases consistency through Android applications.

/*
 * Here is a sample that show how to create a NormalActionBarItem with custom Drawable
 * and content description.
 */
ActionBarItem item = getActionBar().newActionBarItem(NormalActionBarItem.class);
item.setDrawable(R.drawable.ic_title_export).setContentDescription(R.string.gd_export);
addActionBarItem(item);

Note: The ActionBarItem icons I’ve included to GreenDroid are those that are, to my mind, essential to Android applications. If you think some other icons are essential, fill free to contribute. Just make sure they are in accordance with Android guidelines (shape, colors, size, etc.).

New “applying” system

When I created GreenDroid it wasn’t possible to use projects as “libraries”. Fortunately, the latest release of ADT includes a brand new amazing feature: library projects. A complete description is given on the Android Developers Website so I won’t spend time describing it here.

Thanks to that feature, I’ve removed the previous Python script that were used to copy files from the GreenDroid library to your own projects. To apply GreenDroid to your projects, simply follow the process detailed here. The main advantage of this modification is GreenDroid is now more user-friendly and way easier to use. It is also fully compatible with Windows, Mac OS X or Linux.

I hope you’ll have a lot of fun with this new GreenDroid release. As usual, feel free to leave a comment here if you have a GreenDroid-remated question or if you simply want to thank me! Happy coding!

Tous les développeurs friands de technique seront déçus par ce post. En effet, cette fois ci je souhaitais simplement parler de tout et de rien (en rapport avec Android bien sûr). N’allez, tout de même pas croire que ce post est sans intérêt … dites vous plutôt que c’est un état de l’art de mes différentes “actions” récentes sur Android (et également une excuse pour tous ceux qui pensent que je ne suis plus très actif en ce moment ^^)

MetroMap

Certains l’auront probablement remarqué … MetroMap n’est plus disponible sur l’Android Market ou même l’Appslib. Cette absence est entièrement voulue et est la conséquence directe d’une mise en demeure que j’ai reçue il y a maintenant environ 2 semaines.

Reçue via courriel et courrier postal recommandé, cette mise en demeure, envoyée par la RATP elle-même, me donnait deux semaines pour retirer mon application des différents markets Android. La raison de cette demande était simple : la RATP interdit totalement l’utilisation de leurs cartes, logos, etc. sans autorisation préalable. Dans mon cas, le problème venait de l’utilisation inautorisée de la carte du métro parisien.

Un peu enragé par la large base d’utilisateurs ainsi que par le temps passé à réaliser cette application, j’ai décidé de demander une autorisation qu’on m’a gentiment refusé en affirmant qu’aucune autorisation d’utilisation de fond de carte ou de logo n’était donnée pour les applications sur terminaux mobiles. J’ai même essayé de me battre jusqu’à la mort pour ma cause en affirmant que l’application MetroMap s’incrivait parfaitement en complément des applications Android RATP (ce que je pense réellement). La cause s’est malheureusement avéré veine …

Aujourd’hui je suis donc face à diverses options :

  • Laisser tomber purement et simplement (et donc dire adieu à des heures de travail et m’excuser auprès d’utilisateurs fidèles) : ça n’est pas du tout mon genre !
  • Mettre le code source à disposition de tous pour que chacun puisse utiliser/recompiler MetroMap Paris comme il le souhaite : je ne trouve malheureusement pas ça très user-friendly (surtout pour Mme Michu qui a déjà du mal à utiliser l’application “Android Market”) et donc absolument pas viable.
  • Vendre le code au plus offrant : N’ayant toujours pas trouvé d’application “carte de métro” aussi fluide et facile d’utilisation … pourquoi pas ^^
  • Rebondir en utilisant un autre fond de carte du métro parisien : Cela me semble la piste la plus logique … il me faut simplement du temps pour reprendre le code et intégrer une carte dont la license m’autorise son utilisation. Cela peut, tout de même, engendrer certains problèmes. En effet, actuellement les possesseurs de MetroMap disposent encore et toujours du fond de carte RATP (je n’ai pas le pouvoir de forcer la suppression des applications déjà installées). Forcer une mise à jour impliquera un changement forcé du fond de carte et donc une perte probable d’utilisateurs qui se sentiront “brusqué” par ce changement. Pour contrer ce genre de problématique je pense qu’il n’y a qu’une seule et unique possibilité : améliorer MetroMap Paris (fond de carte sur la SD-card, rapatriement des fonds de carte à la première utilisation, amélioration des performances, améliorations de la qualité des images, etc.).

GreenDroid

GreenDroid est un projet que j’ai débuté il y a maintenant 2 ou 3 mois. C’est une librairie dont la vocation principale est de simplifier le développement sur Android tout en uniformisant les interfaces graphiques (à mon goût pas assez consistantes et ergonomiques actuellement sur Android). Cette librairie contient ainsi diverses fonctionnalités pour gérer facilement des ListViews, créer des SegmentedBars ou des ActionBars.

Assez étonné par l’intérêt porté par les développeurs (que je remercie) sur GreenDroid (notamment depuis l’intégration de l’ActionBar), je continue à travailler sur ce projet qui me tient à coeur. L’avenir proche de GreenDroid s’oriente donc vers une modification du système “d’application” de la librairie aux projets l’utilisant ainsi qu’un ajout de plusieurs fonctionnalités (ActionBarItem prédéfinis, ActionBarItem gérant l’état “loading”, etc.)’.

Il est clair que ce genre de projet prend énormément de temps mais c’est une expérience vraiment enrichissante. GreenDroid est né d’une idée simple et évolue au grès de son utilisation dans divers projets. Si vous utilisez GreenDroid, n’hésitez donc pas à remonter vos différentes impressions ou ressentiments sur la philosophie sous-jacente, la facilité d’utilisation, etc. Si vous ne l’utilisez pas encore … je ne pourrais que vous conseiller de sauter le pas !

Après un blog … un livre !?!

Je suis resté extrêmement discret sur le point depuis le début et je pense qu’il devient de plus en plus acceptable de traiter de ce sujet maintenant. Lorsque j’ai créé ce blog, mon objectif était principalement de partager sur un système encore méconnu. Aujourd’hui Android est devenu un acteur incontournable du monde mobile et il est encore amené à évoluer énormément.

C’est donc face à cette certitude que j’ai décidé de pousser l’expérience du blog un peu plus loin … J’ai le plaisir de vous annoncer que j’ai entrepris de rédiger un livre sur le développement sur Android. Ce livre, co-écrit avec Ludovic Perrier (co-fondateur de la société Diotasoft et également co-vainqueur du concours SFR Jeunes Talents Développeur grâce à l’application Didunozat) sera disponible en français et, je l’espère, dans le courant d’octobre.

L’ouvrage abordera le développement sur la plateforme Android en suivant une démarche très pédagogique (truffées d’exemples réutilisables) et complète. Destiné aussi bien aux débutants (explication des concepts élémentaires) qu’aux expérimentés (optimisations diverses), le livre traite de sujets divers et inédits.

Je ne vais pas trop m’étendre sur ce sujet car je pense que la meilleure des options qui s’offrent à vous sera de télécharger la version électronique du livre ou tout simplement d’acheter la version papier. C’est aussi l’occasion pour vous de me remercier pour ce blog ou tout simplement de mon investissement vis à vis d’Android et de la communauté !. Je donnerais bien sûr plus d’infos sur ce super ouvrage dans les mois prochains.

Pour finir, j’aimerai profiter de ce post un peu particulier pour remercier tous les lecteurs de ce blog. En effet, écrire est un plaisir mais se savoir lu et encore plus plaisant et entrainant ! Merci à vous tous. La communauté Android et le système Android tout entier repose sur vos épaules et sur les applications que vous développez. Depuis mes débuts sur Android, j’ai eu l’occasion de voir des choses vraiment innovantes et j’espère sincèrement que ce n’était que le début !!!

Voici maintenant un petit moment que je rédige des articles en anglais. Ces derniers traitent d’un travail sur lequel je passe pas mal de temps et qui, je pense, est nécessaire pour essayer d’uniformiser les applications Android tout en facilitant la vie du développeur : ce projet c’est GreenDroid. Cette fois, j’ai envie de revenir aux origines ! C’est donc avec plaisir que j’écris ces lignes en français, pour les francophones aussi bien débutants qu’expérimentés.

Je ne vais rien vous apprendre en affirmant que le développement sous Android repose principalement sur 2 entités distinctes :

  • Le code source (contenu dans le répertoire src sous Eclipse) écrit en Java et intégrant la logique sous-jacente d’une application
  • Les ressources (contenues dans le répertoire res dans une arborescence classique) qui ont des formes variées (XML, images, etc.). Les ressources n’ont pas de notion de logique mais représentent plus le contenu et la “forme” de l’application

Il existe un très grand nombre de ressources disponibles sous Android. J’ai déjà largement traité de nombreuses d’entre-elles comme les Drawables (dans une présentation que j’ai donné aux Android Developers Labs de Paris - présentation disponible sur SlideShare et code source téléchargeable sur GitHub) ou les layouts (dans presque tous les articles de ce blog : si vous n’avez jamais remarqué, honte à vous !). Il existe énormément d’autres types de ressources sur Android (couleurs, styles, thèmes, etc.) mais nous allons ici nous attarder sur une ressource rarement abordée mais pourtant essentielle : les chaines de caractères et le fichier strings.xml.

Les chaines de caractères simples

Lorsqu’on souhaite utiliser des chaines de caractères dans une application, il suffit d’inclure la chaine dans les ressources de type “string” comme montré ci-dessous :

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="application_name">My Application</string>
    <string name="application_description">This is my first Android application!</string>    
</resources>

La récupération d’une chaine de caractères s’effectue ensuite grâce à son nom (ou name). Le code ci-dessous est extrait d’une Activity (et donc d’un Context) et montre comment récupérer de façon efficace et rapide la valeur d’une chaine de caractères :

final String appName = getString(R.string.application_name);

Lorsque vous ne disposez que du Context (dans une View par exemple), il est nécessaire de d’abord récupérer les ressources :

final String appName = context.getResources().getString(R.string.application_name);

Les chaines de caractères formatées

Il est parfois utile de créer des chaines un peu plus développées que de simple chaines fixes. Imaginons par exemple que nous souhaitions avoir une chaine de caractères décrivant un album de musique et contenant le nombre de chansons ainsi que le titre de l’album. Concaténer manuellement les différentes parties de la chaine de caractères est un travail long est inutile. En effet, Android gère parfaitement les chaines formatées et autorise donc une syntaxe comme montré ci-dessous. Pour une documentation complète sur les possibilités des chaines de caractère formatées, n’hésitez pas à vous reporter à la documentation de Formatter

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="album_description">%1$s contains %2$d songs</string>
</resources>

Pour utiliser la chaine de caractères, il suffit alors d’utiliser le code suivant (dans le contexte d’une Activity):

final String albumDescription = String.format(getString(R.string.album_description), albumName, songCount);

C’est simple non ? Eh bien, comme à son habitude, le framework Android vous facilite encore plus la vie ! La méthode getString(int) a, en effet, été surchargée et accepte un nombre illimité de paramètres :

final String albumDescription = getString(R.string.album_description, albumName, songCount);

Le type plurals

Dans l’exemple précédent, il est possible de rencontrer un problème assez gênant. Lorsque qu’il n’y a qu’une seule chanson dans l’album, l’application va bêtement afficher “Banana contains 1 songs”. Dommage … mais cela peut être géré assez facilement grâce à Android et l’utilisation du type de ressource “plurals” !

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <plurals name="album_description">
        <item quantity="one">%1$s contains %2$d song</item>
        <item quantity="other">%1$s contains %2$d songs</item>
    </plurals>
</resources>

Grâce au fichier ressource ci dessous, nous venons de déclarer une chaine formatée qui se comporte différemment suivant que la quantité affichée a une valeur de un (one) ou plus (other). Dans votre code, rien de plus simple :

final String albumDescription = getQuantityString(R.plurals.album_description, songCount, albumName, songCount);

Note : Mon seul regret avec l’utilisation des ressources de type “plurals” et l’absence d’un item de quantité “zero”. Dans de tel cas, le framework utilise la valeur de other et affiche donc “0 songs”. Je ne comprends pas pourquoi cette valeur a été évincée du framework par Google. Un oubli (j’en doute), une raison particulière (surement mais laquelle ???) ? Vous devrez donc gérer ce cas à la main.

L’internationalisation des chaines de caractères - i18n

Regrouper l’intégralité des chaines de caractères dans les fichiers ressources permet de séparer efficacement le code source et le design des ressources textuelles. Ainsi, lorsque vous devez traduire ou faire traduire votre application, il vous suffit simplement de dupliquer le fichier strings.xml original et de modifier les valeurs de chaque chaines. L’externalisation de l’intégralité des chaines présentes dans votre application (layouts, code source, etc.) et donc vital à l’évolution de votre application. Le code suivant est donc totalement à proscrire de vos applications :

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="This is a TextView" />

Pour finir, il est également possible de faciliter le travail des traducteurs en utilisant le format XLIFF dans vos chaines de caractères. Cette spécification dont la description détaillée est disponible ici permet de laisser le traducteur se concentrer sur le texte à traduire. Personnellement, je trouve cette spécification sympa mais je doute de son utilité dans une application à taille réduite comme c’est le cas pour beaucoup d’applications mobiles.

<plurals name="found_contact">
    <item quantity="one">Found 1 contact</item>
    <item quantity="other">Found <xliff:g id="count">%1$d</xliff:g> contacts</item>
</plurals>

During the past few weeks, a lot of amazing features have been integrated to GreenDroid. Some of those features includes item-based ListViews, XML-based ListViews SegmentedBar, etc. Today, I’d like to introduce you with a brand new addition to the GreenDroid library project: the ActionBar and all of its related classes.

Some of you may know, I’m strongly attached to make Android a great mobile platform. In order to that, I think it is compulsory to create user-friendly UIs. I really believe a great Android UI have to be be clear, need to focus on content and should be VERY easy to use … even if the user is my grandfather!

The concept of ActionBar has been introduced with the Twitter application for Android. More recently, we have seen this widget in the Google I/O 2010 schedule application. To sum up, an ActionBar can be considered as an advanced title bar that is capable of:

  • containing several ActionBaritems (similar to buttons)
  • being styled so that the general look’n'feel of the application is in accordance with the underlying brand/visual identity
  • containing a title to show the user a summary of the screen content
  • featuring several user interaction pattern.

Google recently explained everything about the advantages of using ActionBar in your applications so I won’t spend a lot of time here talking about those key features. If you’re interested in knowing more about the ActionBar UI design pattern, watch the talk given at Google I/O 2010.

Note :As usual, snippets of code below are all extracted from the GDCatolog and GreenDroid projects. Those projects are available on GitHub at the following address: http://github.com/cyrilmottier/GreenDroid

The ActionBar and ActionBarHost classes

As we have previously seen, the ActionBar class represents an enhanced title bar that can be included in your layouts. It supports a large set of features described below:

  • greendroid:title: This is the text that will be used as ActionBar’s title
  • greendroid:type: An ActionBar can be of type normal (the default type) or of type dashboard. A normal ActionBar looks like the picture above. A dashboard ActionBar doesn’t have a “home” button and display an icon that describes the application : the application drawable. Usually, the dashboard type is used only on the main screen of your application
  • greendroid:dividerDrawable: This is the Drawable that is used to divide items. By default, the divider is a 1-pixel width translucent white ColorDrawable

Clickable items can be added to the ActionBar using the addItem(Drawable) or addItem(int) method. Clicks are handled via the ActionBar.OnActionBarListener interface and its onActionBarItemClicked(int) method.

The ActionBarHost is a simple wrapper containing a upper ActionBar (id gd_action_bar) and a lower FrameLayout content view (of id gd_action_bar_content_view).

The GD[List/Tab]Activity

Including ActionBar manually in your layout is a boring task and may be time consuming. To prevent you from doing the same actions over and over again, GreenDroid includes several useful Activitys:

  • GDActivity: Hosts an ActionBarHost
  • GDListActivity: Hosts an ActionBarHost and a ListView.
  • GDTabActivity: Hosts an ActionBarHost and a TabHost as shown below.

How to use the GD-classes

As usual, the GD-classes has been designed focusing on GreenDroid’s development principles: improving easiness, fastness and efficiency!

Applying GreenDroid to your project

I won’t explain how to apply GreenDroid to your project. Indeed, I’ve discussed about that in a very long post that you can find here. Installation instructions are also available in the project’s readme

Make sure you application is a GDApplication

GreenDroid uses information that must be available through the entire application. Some of those information are the application Intent (the Intent that is used when the user pressed the application drawable) or the home Activity class (the class of your main Activity). As a result you need to force your application to be a GDApplication. Simply add android:name="greendroid.app.GDApplication" to the application tag in your AndroidManifest.xml:

The default implementation of GDApplication always returns null values. Changing those values can be done by extending the GDApplication:

package com.cyrilmottier.android.gdcatalog;
 
import greendroid.app.GDApplication;
 
public class CatalogApplication extends GDApplication {
    @Override
    public Class getHomeActivityClass() {
        return CatalogActivity.class;
    }
}

You can now change the class of your application:

<application
    android:icon="@drawable/greendroid_icon"
    android:label="@string/app_name"
    android:theme="@style/Theme.GDCatalog"
    android:name=".CatalogApplication">

Uses the GreenDroid’s base theme

GreenDroid heavily relies on XML resources and especially on styles and themes. In order to use GreenDroid, make sure your application theme inherits from the GreenDroid base theme: @style/Theme.GreenDroid

Create your first GDActivity

When using a GDActivity you don’t need to manually add an ActionBar to your layout. The setActionBarContentView(...) methods take your layout and insert it in an ActionBarHost.

Setting the title of the GDActivity can be done using several ways:

  • Using one of the setTitle methods
  • Adding an extra String with the key ActionBarActivity.GD_ACTION_BAR_TITLE to the Intent that launches your GDActivity
  • Setting a label to the Activity in your AndroidManifest.xml

Your application is notified everytime the user clicked on an ActionBar item via the onHandleActionBarItemClick(int) method.

Let’s start with an example. The following code is a very simple layout composed of a single TextView that will be used as the content of our GDActivity:

<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/text"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center"
    android:textSize="14sp"
    android:textStyle="bold" />

The GDActivity code is given below:

package com.cyrilmottier.android.gdcatalog;
 
import greendroid.app.GDActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
 
public class ActionBarActivity extends GDActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        setActionBarContentView(R.layout.text);
        ((TextView) findViewById(R.id.text)).setText("Screen 1");
 
        getActionBar().addItem(R.drawable.ic_title_export);
        getActionBar().addItem(R.drawable.ic_title_search);
    }
 
    @Override
    public boolean onHandleActionBarItemClick(int position) {
 
        switch (position) {
            case 0:
                Intent intent = new Intent(this, TabbedActionBarActivity.class);
                startActivity(intent);
                return true;
 
            case 1:
                Toast.makeText(this, "Fake feature. Click on the other item instead", Toast.LENGTH_SHORT).show();
                return true;
 
            default:
                return super.onHandleActionBarItemClick(position);
        }
    }
}

The result displayed an screen is shown below

Easily create tabs with GDTabActivity

One of the most useful new GreenDroid’s feature is the ability to rapidly create fancy tabs. The following code shows a demonstration screen containing three tabs:

package com.cyrilmottier.android.gdcatalog;
 
import com.cyrilmottier.android.gdcatalog.util.ColorUtils;
 
import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.TextView;
import greendroid.app.GDTabActivity;
 
public class TabbedActionBarActivity extends GDTabActivity {
 
    private static final String TAB1 = "tab_one";
    private static final String TAB2 = "tab_two";
    private static final String TAB3 = "tab_three";
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        setTitle("Screen 2");
 
        Intent intent = new Intent(this, FakeActivity.class);
        intent.putExtra(FakeActivity.EXTRA_COLOR, Color.RED);
        intent.putExtra(FakeActivity.EXTRA_TEXT, "Content of tab #1");
        addTab(TAB1, "Tab One", intent);
 
        intent = new Intent(this, FakeActivity.class);
        intent.putExtra(FakeActivity.EXTRA_COLOR, Color.GREEN);
        intent.putExtra(FakeActivity.EXTRA_TEXT, "Content of tab #2");
        addTab(TAB2, "Tab Two", intent);
 
        intent = new Intent(this, FakeActivity.class);
        intent.putExtra(FakeActivity.EXTRA_COLOR, Color.BLUE);
        intent.putExtra(FakeActivity.EXTRA_TEXT, "Content of tab #3");
        addTab(TAB3, "Tab Three", intent);
    }
 
    public static class FakeActivity extends Activity {
 
        public static final String EXTRA_COLOR = "com.cyrilmottier.android.gdcatalog.TabbedActionBarActivity$FakeActivity.extraColor";
        public static final String EXTRA_TEXT = "com.cyrilmottier.android.gdcatalog.TabbedActionBarActivity$FakeActivity.extraText";
 
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
 
            final Intent intent = getIntent();
 
            if (intent != null) {
                setContentView(R.layout.text);
 
                TextView textView = (TextView) findViewById(R.id.text);
                textView.setText(intent.getStringExtra(EXTRA_TEXT));
 
                int color = intent.getIntExtra(EXTRA_COLOR, Color.BLACK);
                textView.setBackgroundColor(color);
                textView.setTextColor(ColorUtils.negativeColor(color));
            }
        }
 
    }
 
}

Conclusion

One of the biggest problem with previous releases of Android was the lack of great UI/UXs … I know/think Google is working hard on that right now to help developers creating consistent applications. I hope, GreenDroid will be a great solution to that problem and I strongly encourage you to use it as soon as possible : just keep in mind this is a work in progress that may need to be enhanced by developers like you! Happy coding!

In a previous post, I’ve been introducing you with a library I’m developing. I strongly encourage you to read the long post I have written because it explains almost everything about the GreenDroid library: its purpose, the purpose I’m looking for with it, etc. To sum up, GreenDroid is an approach to unify Android developments and UI/UXs by making application development easier and straightforward.

The first release of GreenDroid focused on creating and populating ListView in a very simple manner. This time, I’ve included a new widget that can be very helpful when designing applications: SegmentedBar. Used with its associated SegmentedHost and SegmentedAdapter classes, a SegmentedBar is really similar to a TabWidget. The main difference relie in the fact a SegmentedBar only uses views and look different:

As you may have noticed, a SegmentedBar looks like the widget that were previously (prior to Froyo) used in the Android Market application to switch between applications types. A SegmentedBar is a bunch of segments. Each segment has an indicator that can be on or off depending on its current state (checked or not). Once you’re tapping a segment, the associated view is displayed.

Note :The snippets of code below are all extracted from the GDCatolog and GreenDroid projects. Those projects are all available on GitHub at the following address: http://github.com/cyrilmottier/GreenDroid

As a developer, you probably prefer reading code than explainations … I’ve implementing a really tiny application available in the GDCatalog application that uses the 3 classes given above. The first thing to do is to created our layout:

<?xml version="1.0" encoding="utf-8"?>
<greendroid.widget.SegmentedHost
    xmlns:greendroid="http://schemas.android.com/apk/res/com.cyrilmottier.android.gdcatalog"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/segmentedHost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    greendroid:segmentedBar="@+id/segmentedBar"
    greendroid:segmentedContentView="@+id/segmentedContentView">
 
    <greendroid.widget.SegmentedBar
        android:id="@+id/segmentedBar"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
 
    <FrameLayout
        android:id="@+id/segmentedContentView"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1.0"
        android:foreground="@drawable/gd_shadow_top" />
 
</greendroid.widget.SegmentedHost>

This layout is composed of a root SegmentedHost element that fills (or match according to the brand new match_parent value) the size of the screen. A SegmentedHost is a wrapper that contains a SegmentedBar and a content view (FrameLayout). This two elements will be filled with the data provided by a SegmentedAdapter. The XML attributes greendroid:segmentedBar and greendroid:segmentedContentView are mandatory and must be used to inform the SegmentedHost which subview must be used. I assume the rest is pretty clear so I won’t explain anything else but the android:foreground attribute. Android often uses shadows to separate two main areas on screen. The GreenDroid library includes shadows (named gd_shadow_top and gd_shadow_bottom) that can be reused easily to enhance your UIs.

Now our layout is ready, the only thing we have to do is to fill the SegmentedHost with the appropriate data. Data are provided through a SegmentedAdapter as shown below:

package com.cyrilmottier.android.gdcatalog;
 
import com.cyrilmottier.android.gdcatalog.util.ColorUtils;
 
import greendroid.widget.SegmentedAdapter;
import greendroid.widget.SegmentedHost;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.TextView;
 
public class SegmentedActivity extends Activity {
 
    private final Handler mHandler = new Handler();
    private PeopleSegmentedAdapter mAdapter;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.segmented_controls);
 
        SegmentedHost segmentedHost = (SegmentedHost) findViewById(R.id.segmentedHost);
 
        mAdapter = new PeopleSegmentedAdapter();
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mAdapter.mReverse = true;
                mAdapter.notifyDataSetChanged();
            }
        }, 4000);
 
        segmentedHost.setAdapter(mAdapter);
    }
 
    private class PeopleSegmentedAdapter extends SegmentedAdapter {
 
        public boolean mReverse = false;
 
        @Override
        public View getView(int position, ViewGroup parent) {
 
            TextView textView = new TextView(SegmentedActivity.this);
            textView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
            textView.setGravity(Gravity.CENTER);
 
            final int color = getColor(mReverse ? ((getCount() - 1) - position) : position);
            textView.setBackgroundColor(color);
            textView.setTextColor(ColorUtils.negativeColor(color));
            // It's not necessary to compute the "reversed" position as the
            // getSegmentTitle will do it automatically
            textView.setText(getSegmentTitle(position));
 
            return textView;
        }
 
        @Override
        public int getCount() {
            return 4;
        }
 
        @Override
        public String getSegmentTitle(int position) {
 
            switch (mReverse ? ((getCount() - 1) - position) : position) {
                case 0:
                    return getString(R.string.segment_1);
                case 1:
                    return getString(R.string.segment_2);
                case 2:
                    return getString(R.string.segment_3);
                case 3:
                    return getString(R.string.segment_4);
            }
 
            return null;
        }
 
        private int getColor(int position) {
            switch (position) {
                case 0:
                    return Color.RED;
                case 1:
                    return Color.GREEN;
                case 2:
                    return Color.BLUE;
                case 3:
                    return Color.CYAN;
            }
            return Color.TRANSPARENT;
        }
    }
 
}

In order to create your own SegmentedAdapter, you simply need to extend the SegmentedAdapter and override the three following methods:

  • int getCount(): This method must return the number of segments your SegmentedBar will contain.
  • String getSegmentTitle(int position): Returns the title for the segment at the given position
  • View getView(int position, ViewGroup parent): This method is very similar to the traditionnal getView method. The only difference is there is no convertView parameter. Actually this method will be called only once in the lifetime of your SegmentedHost. Once created, The SegmentedHost will automatically keep a reference on the generated view. Hence, there is no need to recycle views. If you want to reorganize your segments, simply call notifyDataSetChanged() as shown in the exemple above

Using a SegmentedBar is very useful when your screen have a lot of information that can be split in several pieces. A great sample would be an “About” screen : you can now split the developer information from the legal or partners information. I hope you’ll use this new widget as well as all other cool features integrated to the GreenDroid library. Happy coding and see you soon for new amazing GreenDroid features!