22
2012
[Tutoriel Android] Partie 18 – Contrôles personnalisés
Aujourd’hui nous allons aborder le thème des contrôles personnalisés.
Tout d’abord qu’est-ce qu’un contrôle personnalisé ? (Custom control ou encore Custom component).
Hé bien un c’est un composant que nous allons utiliser dans notre application pour afficher une donnée, nous allons développer un contrôle personnalisé car soit ce composant n’existe pas dans le SDK Android, soit parce que cet élément est redondant dans toute l’interface.
Le cas où le composant n’existe pas
- Diagramme (camembert,bâton,etc…)
- Compteur de vitesse
- Thermomètre
- Etc…
Cas où le composant existe mais on le modifie pour le réutiliser tout le temps
- Chargement d’une image
- Bannière publicitaire
- Menu
- etc…
Héritage !
L’héritage est très important dans la création d’un contrôle.
Les contrôles se différencies avec deux grands types
- Affichage à base de canvas (View)
- Affichage à base d’OpenGL (SurfaceView)
- On part d’une base vierge (View)
- On part d’un élément existant (TextView,etc…)
- On part d’une liste d’éléments (ViewGroup,LinearLayout,etc…)
Chargement d’une image asynchrone
Imaginons que nous avons une ListView avec des images à charger, pour rendre notre application performante nous allons utiliser un thread pour charger nos images sinon on risque de bloquer l’utilisateur si la vitesse de téléchargement est trop lente.
Donc il nous faut 1 ImageView et 1 Thread à chaque fois, mais c’est embêtant j’ai 2 activités qui utilises le même fonctionnement, voir même plusieurs applications !
Pas d’inquiétudes matelot nous allons faire un contrôle pour cela
Tout d’abord on va partir d’un contrôle existant (ImageView) puis embarquer un Thread dans ce contrôle pour gérer le chargement en asynchrone (AsyncTrask).
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.widget.ImageView;
/***
* ImageLoader
*
* @author ace
*
*/
public class ImageLoaderView extends ImageView {
/**
* Constructeur hérité
*
* @param context
* @param attrs
*/
public ImageLoaderView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void loadImage(String url) {
new DownloadImage(this).execute(url);
}
private class DownloadImage extends AsyncTask {
final ImageView imageView;
public DownloadImage(ImageView imageView) {
this.imageView = imageView;
}
@Override
protected Bitmap doInBackground(String... params) {
if (params.length == 0)
return null;
try {
URL url = new URL(params[0]);
InputStream stream = url.openStream();
Bitmap bf = BitmapFactory.decodeStream(stream);
return bf;
} catch (MalformedURLException e) {
return null;
} catch (IOException e) {
return null;
}
}
@Override
protected void onPostExecute(Bitmap result) {
if(result != null)
imageView.setImageBitmap(result);
super.onPostExecute(result);
}
}
}
Je vous donne la classe directement, pas besoin d’explication vous savez déjà charger une image (Partie 8) et vous connaissez aussi les threads (Partie 9).
Nous allons maintenant utiliser notre nouveau composant dans notre layout principal
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <com.aceart.formation.component.ImageLoaderView android:id="@+id/imageLoader1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <com.aceart.formation.component.ImageLoaderView android:id="@+id/imageLoader2" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <com.aceart.formation.component.ImageLoaderView android:id="@+id/imageLoader3" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
Trois images loader avec chacun un ID.
Dirigeons nous maintenant vers notre activité
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final ImageLoaderView imgL1 = (ImageLoaderView) findViewById(R.id.imageLoader1);
imgL1.loadImage("http://www.laptopspirit.fr/wp-content/uploads/new/mandriva-logo.thumbnail.jpg");
final ImageLoaderView imgL2 = (ImageLoaderView) findViewById(R.id.imageLoader2);
imgL2.loadImage("http://i73.photobucket.com/albums/i240/jazzk1/android-logo-mask.png");
final ImageLoaderView imgL3 = (ImageLoaderView) findViewById(R.id.imageLoader3);
imgL3.loadImage("http://upload.wikimedia.org/wikipedia/fr/7/78/Quakelive_logo_300.png");
}
On récupère nos ImageLoader et on effectue l’action de chargement.
Lancer l’application et miracle le chargement est en asynchrone et pas besoin de réécrire le code et qui plus est vous pouvez réutiliser ce code dans les ListView etc…
Création d’un graphique
Nous allons maintenant voir comment créer un custom components grâce au canvas.
Les étapes :
- Définir le modèle de données (Classe Item)
- Créer le contrôle (Héritage de la classe View)
- Implémenter la méthode onDraw
- Dessiner le diagramme grâce au canvas
- Afficher
Rien de plus simple en fait.
Voici la classe item que nous utiliserons pour fournir en données notre vue
public class PieChartItem {
private double value;
private int color;
public PieChartItem(double value, int color) {
this.value = value;
this.color = color;
}
public double getValue() {
return value;
}
public void setValue(double value) {
this.value = value;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
}
Notre objet contient une valeur et une couleur.
Notre vue maintenant
public class PieChartView extends View {
private List<PieChartItem> items;
public PieChartView(Context context, AttributeSet attrs) {
super(context, attrs);
items = new ArrayList<PieChartItem>();
}
@Override
protected void onDraw(Canvas canvas) {
drawChart(canvas);
super.onDraw(canvas);
}
private void drawChart(Canvas canvas) {
if (items != null) {
}
}
}
On a bien hérité de la vue, on a le bon constructeur et la méthode onDraw est implémentée
Il reste plus qu’a appeler notre petit diagramme dans le layout
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <com.aceart.formation.component.PieChartView android:id="@+id/pieChart" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@android:color/white" /> </LinearLayout>
Je vous donnes le code d’exemple tout de même pour pouvoir vous amusez
Classe complète:
public class PieChartView extends View {
private List<PieChartItem> items;
public PieChartView(Context context, AttributeSet attrs) {
super(context, attrs);
items = new ArrayList<PieChartItem>();
}
@Override
protected void onDraw(Canvas canvas) {
drawChart(canvas);
super.onDraw(canvas);
}
private void drawChart(Canvas canvas) {
if (items != null) {
// angle de départ
float angleDepart = 0.f;
double somme = getSomme();
// Zone carrée
RectF zoneDessin = new RectF(0, 0, getWidth(), getWidth());
// Pinceau
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);
// On passe chaque item en revue
for (PieChartItem item : items) {
// on change la couleur
paint.setColor(item.getColor());
// On calcul l'angle d'ouverutre
float sweepAngle = (float) ((item.getValue() / somme) * 360);
// On dessine l'arc
canvas.drawArc(zoneDessin, angleDepart, sweepAngle, true, paint);
// On change l'angle de départ
angleDepart += sweepAngle;
}
}
}
private double getSomme() {
double somme = 0;
for (PieChartItem item : items) {
somme += item.getValue();
}
return somme;
}
public void addValue(PieChartItem item) {
this.items.add(item);
}
public void setValues(List<PieChartItem> items) {
this.items = items;
}
}
Les appels dans l’activité principale :
public class FormationCustomComponentActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final PieChartView pieChartView = (PieChartView) findViewById(R.id.pieChart);
pieChartView.addValue(new PieChartItem(25, Color.GREEN));
pieChartView.addValue(new PieChartItem(75, Color.RED));
}
}
Et le rendu pour finir
Maintenant à vous de vous amuser à créer vos propres composants.
Articles relatifs
-
Cyrille
-
http://www.ace-art.fr/wordpress Acesyde
Survie
Catégories
- Andengine (5)
- Android (20)
- Application (1)
- Articles (1)
- Non classé (2)
- Programmation (30)
Nuage
Commentaires récents
- Paumé dans [Tutoriel Honeycomb] Partie 1 – Les actions bars
- Acesyde dans [Tutoriel android] Partie 3 – Une petite intention ?
- paul dans [Tutoriel Honeycomb] Partie 1 – Les actions bars
- Sne dans [Tutoriel android] Partie 3 – Une petite intention ?
- Vivien-57 dans [Tutoriel Android] Partie 13 – L’appareil photo
Archives
- janvier 2012 (2)
- novembre 2011 (1)
- octobre 2011 (3)
- juillet 2011 (3)
- juin 2011 (1)
- décembre 2010 (4)
- octobre 2010 (3)
- septembre 2010 (5)
- juillet 2010 (8)
- avril 2010 (6)

Un article de






