I. Qu'est-ce que les Drawables ?▲
Une ressource Drawable est un concept général pour un élément graphique qui peut être redimensionné. Le cas le plus simple est un fichier graphique (bitmap) qui serait représenté sous Android par une classe BitmapDrawable.
Chaque Drawable est stocké en tant que fichier individuel dans un des dossiers res/drawable. En général, vous stockez des bitmaps à résolutions différentes dans les sous-dossiers -mdpi, -hdpi, -xhdpi, -xxhdpi du dossier res/drawable. L'assistant de création de projet d'ADT crée par défaut ces dossiers. Si les bitmaps se trouvent dans un autre dossier, le système Android sélectionne automatiquement celui approprié en fonction de la configuration de l'appareil.
Si vous ne fournissez pas les bitmaps pour toutes les résolutions supportées, le système Android met à l'échelle, vers le haut ou vers le bas, celui qui se rapproche le plus. Cela est généralement indésirable, car le bitmap peut être flou.
En plus des fichiers graphiques, Android prend en charge les « drawables XML » et les « 9-patch graphics ».
Les « drawables XML » sont utilisés pour décrire les formes (couleur, bordure, gradient), l'état, les transitions et plus encore.
Les « 9-patch graphics » sont utilisés pour définir la partie d'une image qui devrait être étirée si la vue qui l'utilise est plus large.
Les drawables peuvent également être écrits en code Java. Chaque objet qui implémente un Drawable peut être utilisé comme un Drawable dans le code.
II. L'utilisation des drawables pour des vues▲
Les drawables sont désignés en XML par @drawable/filename où le nom de fichier filename est celui sans l'extension. Par exemple, pour accéder au Drawable res/drawable/hello.png, vous pouvez utiliser @drawable/hello comme le montre l'extrait de code suivant :
<TextView
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
android
:
id
=
"@+id/textView1"
android
:
layout_width
=
"wrap_content"
android
:
layout_height
=
"wrap_content"
android
:
background
=
"@drawable/hello"
android
:
text
=
"@string/hello_world"
/>
Dans le code, vous pouvez également assigner des drawables aux vues. La plupart des vues acceptent un ID de ressource comme paramètre en entrée. Par exemple, le code suivant montre comment définir un drawable comme arrière-plan pour une ImageView :
ImageView imageView =
(
ImageView) findViewById
(
R.id.image);
imageView.setImageResource
(
R.drawable.hello);
III. Chargement des bitmaps et des drawables▲
Android vous permet d'utiliser la classe Bitmap pour travailler avec des bitmaps. Cette section explique comment créer des objets Bitmap dans le code Java et comment les convertir en Drawable, et vice versa.
Si nécessaire, vous pouvez charger n'importe quel fichier bitmap accessible dans votre code et le convertir en objet drawable.
L'exemple de code suivant montre comment créer un objet Bitmap pour le dossier assets et l'assigner à une ImageView :
// Récupérer l'AssetManager
AssetManager manager =
getAssets
(
);
// lire un Bitmap depuis Assets
InputStream open
=
null
;
try
{
open
=
manager.open
(
"logo.png"
);
Bitmap bitmap =
BitmapFactory.decodeStream
(
open
);
// Assigner le bitmap à une ImageView dans cette mise en page
ImageView view =
(
ImageView) findViewById
(
R.id.imageView1);
view.setImageBitmap
(
bitmap);
}
catch
(
IOException e) {
e.printStackTrace
(
);
}
finally
{
if
(
open
!=
null
) {
try
{
open
.close
(
);
}
catch
(
IOException e) {
e.printStackTrace
(
);
}
}
}
Vous pouvez également accéder, par votre code source, aux drawables de votre dossier res/drawable en tant qu'objets Bitmap. Le code suivant illustre cela :
Bitmap b =
BitmapFactory.decodeResource
(
getResources
(
), R.drawable.ic_action_search);
Vous pouvez créer une image bitmap à l'échelle sur la base d'une nouvelle définition de la largeur et de la hauteur en pixel :
Bitmap originalBitmap =
<
initial setup>
;
Bitmap resizedBitmap =
Bitmap.createScaledBitmap
(
originalBitmap, newWidth, newHeight, false
);
Pour convertir un objet Bitmap en Drawable, vous pouvez utiliser le code suivant :
# Conversion de Bitmap en Drawable
Drawable d =
new
BitmapDrawable
(
getResources
(
),bitmap);
IV. Drawables XML▲
IV-A. Shape drawables▲
Les « shape drawables » sont des fichiers XML qui permettent de définir un objet géométrique avec des couleurs, des bordures et des gradients qui peuvent être assignés aux vues. L'avantage de l'utilisation des « shape drawables XML » c'est qu'ils s'adaptent automatiquement à la bonne taille.
Le code suivant montre un exemple de « shape drawable » :
<?xml version="1.0" encoding="UTF-8"?>
<shape
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
android
:
shape
=
"rectangle"
>
<stroke
android
:
width
=
"2dp"
android
:
color
=
"#FFFFFFFF"
/>
<gradient
android
:
endColor
=
"#DDBBBBBB"
android
:
startColor
=
"#DD777777"
android
:
angle
=
"90"
/>
<corners
android
:
bottomRightRadius
=
"7dp"
android
:
bottomLeftRadius
=
"7dp"
android
:
topLeftRadius
=
"7dp"
android
:
topRightRadius
=
"7dp"
/>
</shape>
Vous pouvez par exemple assigner ce drawable à la propriété arrière-plan de votre mise en page :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
android
:
layout_width
=
"match_parent"
android
:
layout_height
=
"match_parent"
android
:
background
=
"@drawable/myshape"
android
:
orientation
=
"vertical"
>
<EditText
android
:
id
=
"@+id/editText1"
android
:
layout_width
=
"match_parent"
android
:
layout_height
=
"wrap_content"
>
</EditText>
<RadioGroup
android
:
id
=
"@+id/radioGroup1"
android
:
layout_width
=
"match_parent"
android
:
layout_height
=
"wrap_content"
>
<RadioButton
android
:
id
=
"@+id/radio0"
android
:
layout_width
=
"wrap_content"
android
:
layout_height
=
"wrap_content"
android
:
checked
=
"true"
android
:
text
=
"@string/celsius"
>
</RadioButton>
<RadioButton
android
:
id
=
"@+id/radio1"
android
:
layout_width
=
"wrap_content"
android
:
layout_height
=
"wrap_content"
android
:
text
=
"@string/fahrenheit"
>
</RadioButton>
</RadioGroup>
<Button
android
:
id
=
"@+id/button1"
android
:
layout_width
=
"wrap_content"
android
:
layout_height
=
"wrap_content"
android
:
text
=
"@string/calc"
android
:
onClick
=
"myClickHandler"
>
</Button>
</LinearLayout>
IV-B. State drawables▲
Les « state drawables » permettent de définir des états. Pour chaque état, l'on peut assigner à la vue un drawable différent. Par exemple, le code suivant définit les différents drawables pour un bouton en fonction de son état :
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
>
<item
android
:
drawable
=
"@drawable/button_pressed"
android
:
state_pressed
=
"true"
/>
<item
android
:
drawable
=
"@drawable/button_checked"
android
:
state_checked
=
"true"
/>
<item
android
:
drawable
=
"@drawable/button_default"
/>
</selector>
IV-C. Les « transition drawables »▲
Les « transition drawables » permettent de définir les transitions qui peuvent être déclenchées dans le code :
<?xml version="1.0" encoding="utf-8"?>
<transition
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
>
<item
android
:
drawable
=
"@drawable/first_image"
/>
<item
android
:
drawable
=
"@drawable/second_image"
/>
</transition>
final
ImageView image =
(
ImageView) findViewById
(
R.id.image);
final
ToggleButton button =
(
ToggleButton) findViewById
(
R.id.button);
button.setOnClickListener
(
new
OnClickListener
(
) {
@Override
public
void
onClick
(
final
View v) {
TransitionDrawable drawable =
(
TransitionDrawable) image.getDrawable
(
);
if
(
button.isChecked
(
)) {
drawable.startTransition
(
500
);
}
else
{
drawable.reverseTransition
(
500
);
}
}
}
);
V. Les « animation drawables »▲
Vous pouvez également définir un drawable d'animation et l'affecter à une vue par la méthode setBackgroundResource() :
<!-- Les cadres animation sont les fichiers phase*.png du dossier res/drawable/ -->
<animation-list
android
:
id
=
"@+id/selected"
android
:
oneshot
=
"false"
>
<item
android
:
drawable
=
"@drawable/phase1"
android
:
duration
=
"400"
/>
<item
android
:
drawable
=
"@drawable/phase2"
android
:
duration
=
"400"
/>
<item
android
:
drawable
=
"@drawable/phase3"
android
:
duration
=
"400"
/>
</animation-list>
ImageView img =
(
ImageView)findViewById
(
R.id.yourid);
img.setBackgroundResource
(
R.drawable.your_animation_file);
// Récupérer l'objet AnimationDrawable.
AnimationDrawable frameAnimation =
(
AnimationDrawable) img.getBackground
(
);
// Démarrer l'animation (lecture en boucle par défaut).
frameAnimation.start
(
);
VI. « 9 Patch Drawables »▲
Les « 9 Patch drawables » sont des Drawables qui possèdent une bordure supplémentaire d'un pixel. Sur le dessus et à gauche, vous définissez la zone qui doit être mise à l'échelle si le Drawable est trop petit pour la vue. Il s'agit de la zone d'étirage.
Sur le côté droit et le bas, vous définissez la zone où doit être placé un texte si le Drawable est utilisé sur une vue qui peut afficher un texte dessus, par exemple un bouton.
ADT fournit le programme draw9patch dans le dossier d'installation android-sdk/tools, ce qui facilite la création des « 9 Patch drawables ».
Un joli générateur en ligne de « 9 Patch drawables » peut être trouvé à l'adresse : Générateur Nine-patch simple.
VII. Drawables customisés▲
Vous pouvez également créer des « Drawable customisés » qui peuvent utiliser l'API Canvas pour leur affichage. Vous pouvez utiliser toutes les fonctionnalités de l'API Canvas pour adapter ces drawables à votre besoin.
VIII. Exercice : créez des drawables customisés Exercise: Create Custom Drawables▲
Note
Cet exemple est basé sur un article du blog de Roman Guy.
Créez un projet Android appelé com.vogella.android.drawables.custom basé sur le template Empty Activity.
Créez la classe Drawable personnalisée suivante :
package
com.vogella.android.drawables.custom;
import
android.graphics.Bitmap;
import
android.graphics.BitmapShader;
import
android.graphics.Canvas;
import
android.graphics.ColorFilter;
import
android.graphics.Paint;
import
android.graphics.PixelFormat;
import
android.graphics.RectF;
import
android.graphics.Shader;
import
android.graphics.drawable.Drawable;
public
class
MyRoundCornerDrawable extends
Drawable {
private
Paint paint;
public
MyRoundCornerDrawable
(
Bitmap bitmap) {
BitmapShader shader;
shader =
new
BitmapShader
(
bitmap, Shader.TileMode.CLAMP,
Shader.TileMode.CLAMP);
paint =
new
Paint
(
);
paint.setAntiAlias
(
true
);
paint.setShader
(
shader);
}
@Override
public
void
draw
(
Canvas canvas) {
int
height =
getBounds
(
).height
(
);
int
width =
getBounds
(
).width
(
);
RectF rect =
new
RectF
(
0.0
f, 0.0
f, width, height);
canvas.drawRoundRect
(
rect, 30
, 30
, paint);
}
@Override
public
void
setAlpha
(
int
alpha) {
paint.setAlpha
(
alpha);
}
@Override
public
void
setColorFilter
(
ColorFilter cf) {
paint.setColorFilter
(
cf);
}
@Override
public
int
getOpacity
(
) {
return
PixelFormat.TRANSLUCENT;
}
}
Pour l'utiliser, modifiez votre fichier de mise en page comme suit :
<RelativeLayout
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
xmlns
:
tools
=
"http://schemas.android.com/tools"
android
:
layout_width
=
"match_parent"
android
:
layout_height
=
"match_parent"
tools
:
context
=
".MainActivity"
>
<ImageView
android
:
id
=
"@+id/image"
android
:
layout_width
=
"fill_parent"
android
:
layout_height
=
"fill_parent"
android
:
layout_centerHorizontal
=
"true"
android
:
layout_centerVertical
=
"true"
android
:
contentDescription
=
"TODO"
/>
</RelativeLayout>
Modifiez votre classe MainActivity comme suit (le code suppose que vous ayez une image bitmap appelée dog.png dans votre dossier drawable) :
package
com.vogella.android.drawables.custom;
import
java.io.InputStream;
import
android.app.Activity;
import
android.graphics.Bitmap;
import
android.graphics.BitmapFactory;
import
android.os.Bundle;
import
android.view.Menu;
import
android.widget.ImageView;
public
class
MainActivity extends
Activity {
@Override
protected
void
onCreate
(
Bundle savedInstanceState) {
super
.onCreate
(
savedInstanceState);
setContentView
(
R.layout.activity_main);
ImageView button =
(
ImageView) findViewById
(
R.id.image);
InputStream resource =
getResources
(
).openRawResource
(
R.drawable.dog);
Bitmap bitmap =
BitmapFactory.decodeStream
(
resource);
button.setBackground
(
new
MyRoundCornerDrawable
(
bitmap));
}
}
IX. Liens et littérature▲
X. Remerciements Developpez▲
Vous pouvez retrouver l'article original à l'adresse Android Drawables - Tutorial. Nous remercions Lars Vogel qui nous a aimablement autorisés à traduire et héberger ses articles.
Nous remercions aussi Mishulyna pour sa traduction, ainsi que milkoseck pour sa relecture orthographique.
N'hésitez pas à commenter cet article ! 1 commentaire