Вы находитесь на странице: 1из 67

JMF (Tous droits rservs) 1

Chapitre 3 bis
Les interfaces utilisateurs
avancs avec Android
JMF (Tous droits rservs) 2
Les IHM des smartphones
en 2012

Pas seulement clavier cran

Mais cran tactile

Acclromtre

GPS

Enregistrement de messages audio (notes audio)

Prendre des photos, des vidos, les envoyer par le


rseau (MMS)

SMS

Tlphone
JMF (Tous droits rservs) 3
Rvision de lpisode
prcdent

En Android, on construit les !M plut"t avec un #ichier $M% rang dans


res\layout mon_ihm.xml contenant par e&emple '

(e #ichier est repr dans le code )ava par R.layout.nomBaseFichier


et on positionne l*!M de l*activit + l*aide de ce #ichier par
setContentView(R.layout.nomBaseFichier);

,n rcupre un composant graphi-ue particulier de l*!M par la mthode


.miracle. findViewById(R.id.idDuComposant)/

0emar-ue ' les R. sont des int -ui ont t gnr par l*environnement
dans le #ichier R.java
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout ...
<TextView
...
android:id="@+id/text1" />
setContentView(R.layout.mon_ihm);
TextView tx = (TextView) findViewById(R.id.text1);
JMF (Tous droits rservs) 4
!aille " diffrence entre p#$
dp$ dip$ sp %1&3'

p& ' Pi&els 1 corresponds to actual pi&els on the screen

in ' nches 1 2ased on the physical si3e o# the screen

mm ' Millimeters 1 2ased on the physical si3e o# the screen

pt ' Points 1 4567 o# an inch 2ased on the physical si3e o# the screen

source '
http://stackoverflow.com/questions/2025282/differe
nce-of-px-dp-dip-and-sp-in-android
JMF (Tous droits rservs) 5
!aille " diffrence entre p#$
dp$ dip$ sp %2&3'

dp ' 8ensity1independent Pi&els 1 an a2stract unit that is 2ased on the


physical density o# the screen9 These units are relative to a 4:; dpi screen,
so one dp is one pi&el on a 4:; dpi screen9 The ratio o# dp1to1pi&el <ill
change <ith the screen density, 2ut not necessarily in direct proportion9
=ote' The compiler accepts 2oth .dip. and .dp., though .dp. is more
consistent <ith .sp.

En #ait en gnral dp > (resolution en dpi54:;) p& 9 Sur un cran de


rsolution de 4:; dpi, dp > p& mais si la rsolution est ?7; dpi, on a plut"t
4 dp > 7 pi&els

(onclusion /' e&pression en dp >@ le systme convertit cette unit en pi&els


physi-ues >@ l*image aura la mAme taille -uel -ue soit l*cran

source '
http://stackoverflow.com/questions/11667907/android-
emulator-failed-to-allocate-memory-8/11868277#11868277
JMF (Tous droits rservs) 6
!aille " diffrence entre p#$
dp$ dip$ sp %3&3'

sp ' Scale1independent Pi&els 1 this is liBe the dp unit, 2ut it is also


scaled 2y the user*s #ont si3e pre#erence9 t is recommend you use
this unit <hen speci#ying #ont si3es, so they <ill 2e adCusted #or 2oth
the screen density and user*s pre#erences

source '
http://stackoverflow.com/questions/2025282/differe
nce-of-px-dp-dip-and-sp-in-android
JMF (Tous droits rservs) 7
Les bouton radios

A l*intrieur d*une 2oite de regroupement ' le RadioGroup

Dn android.widget.RadioGroup est un ViewGroup

est, par e&emple, cod par '


<RadioGroup
android:id="@+id/rgGroup1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton android:id="@+id/RB1" android:text="Button1" />
<RadioButton android:id="@+id/RB2" android:text="Button2" />
<RadioButton android:id="@+id/RB3" android:text="Button3" />
</RadioGroup>
JMF (Tous droits rservs) 8
(estion des vnements
sur les bouton radios

(*est similaire au& 2outons .poussoirs.

Avec le code prcdent '


...
rb1 = (RadioButton) findViewById(R.id.RB1);
...
rb1.setOnClickListener(new RadioGroup.OnClickListener() {
public void onClick(View v){
// code lanc lorsque l'utilisateur slectionne
// le premier bouton radio
}
});
JMF (Tous droits rservs) 9
)t*les et !h+mes

Dn style est un ensem2le de proprits prcisant l*aspect de


composants graphi-ues (View)

l est d#ini dans un #ichier $M% spar de l*!M

(ette notion est similaire au (SS ((ascading StyleSheets) pour le


<e2 avec la mAme philosophie ' sparer le contenu de l*aspect

8e mAme -ue pour les (SS, ces in#ormations de style sont


hirarchises

Dn thme est un style pour une Activity

Dne activity ayant un thme associ transmets les indications du


thme + toutes les View contenus dans l*activit

source '
developper.android.com/docs/guide/topics/ui/themes.html
JMF (Tous droits rservs) 10
)parer contenu et aspect
avec les st*les

Au lieu d*crire
on crira plut"t
et les in#ormations de style sont repres par l*identi#icateur
CodeFont

CodeFont est en #ait une entre (i9e9 un lement $M%) dans un


#ichier de style
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#00FF00"
android:typeface="monospace"
android:text="@string/hello" />
<TextView
style="@style/CodeFont"
android:text="@string/hello" />
JMF (Tous droits rservs) 11
,ichier de st*les

Dn #ichier de styles est un #ichier $M% de nom -uelcon-ue rang dans


res/values9 Son noeud racine doit Atre resources9 E&emple

(ha-ue style est un lment $M% style9 %e nom du style est la valeur de
l*attri2ut name9 l contient une suite de sous lments item prcisant une
partie du style9 %e corps de la 2alise item est la valeur de cet item

%es styles peuvent Atre rangs par ar2orescence9 ,n le prcise par l*attri2ut
(optionnel) parent
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CodeFont" parent="@android:style/TextAppearance.Medium">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">#00FF00</item>
<item name="android:typeface">monospace</item>
</style>
</resources>
JMF (Tous droits rservs) 12
Hrita-e des st*les

8#inir une nouvelle valeur pour un attri2ut de style crase l*ancienne valeur
(si elle e&iste) pour cet attri2ut

,n peut hriter de styles prd#inis par Android et, dans ce cas, on utilise
parent comme dans '

,n peut hriter de ses propres styles et, dans ce cas, on utilise la notation .
comme dans '
%e style d#ini est CodeFont.Red9 l rcupre les valeurs du style
CodeFont9 ,n l*utilise comme dans @style/CodeFont.Red

,n peut crer une ar2orescence de style comme CodeFont.Red.Big


<style name="GreenText" parent="@android:style/TextAppearance">
<item name="android:textColor">#00FF00</item>
</style>
<style name="CodeFont.Red">
<item name="android:textColor">#FF0000</item>
</style>
JMF (Tous droits rservs) 13
Les th+mes

Dn style appli-u + un Viewgroup ne se propage pas pour les composants


contenus dans le ViewGroup

Dn thme appli-u + une activit est propag + tous les composants de


l*activit

%es indications de thme sont crits dans le AndroidManifest.xml +


l*aide l*attri2ut android:theme de la 2alise application '

,n peut utiliser les thmes prd#inis d*Android '

%es styles et thmes proposs par Android sont accessi2les + partir de


http://developer.android.com/guide/topics/ui/themes.html#Platfo
rmStyles
<application android:theme="@style/CodeFont">
<activity android:theme="@android:style/Theme.Dialog">
JMF (Tous droits rservs) 14
Composants IHM avancs

(ertains composants graphi-ues permettent d*a##icher 2eaucoup d*items


par des mcanismes de d#ilement9 (e sont '

les Spinner, les Gallery, les GridView, les ListView

l y en a d*autres9 Eoir + Apis 8emos F Eie<s


JMF (Tous droits rservs) 15
AdapterView et Adapter

%es composants graphi-ues -ui a##ichent un ensem2le d*items sont des


AdapterViews

(es composants sont trs utiles si les donnes -u*ils a##ichent ne sont pas
connues + la cration du programme mais seront charges dynami-uement

Pour #ournir les items + ces composants graphi-ues, on utilise des Adapter

(omme AdapterView est en #ait AdapterView<T extends


android.widget.Adapter>, un AdapterView est touCours associ + un
Adapter

%*Adapter sert de lien avec les donnes + a##icher et l*AdapterView9 Gre#


c*est le design pattern adapter

%es AdapterView grent aussi les vnements (i9e9 les interactions) sur le
composant graphi-ue avec le-uel ils sont associs9 (*est + la #ois un design
pattern vue et controleur
JMF (Tous droits rservs) 16
AdapterView$ Adapter et
compa-nie . %1&2'

android.widget.AdapterView<T extends
android.widget.Adapter> est une classe a2straite gnri-ue

android.widget.Adapter est une inter#ace9 Geaucoup de classes


implmentent cette inter#ace ' ArrayAdapter<T>, BaseAdapter

SpinnerAdapter et ListAdapter sont des inter#aces -ui hritent


de Adapter

Spinner, Gallery, GridView, ListView sont des sous classes


concrtes d*AdapterView

%*association entre un AdapterView et un Adapter est #aite +


l*aide de la mthode
public void setAdapter (T adapter)

Huestion ' ,I est indi-u -ue le paramAtre T est un type


implmentant Adapter J

0ponse ' 8ans la d#inition de la classe AdapterView


JMF (Tous droits rservs) 17
AdapterView$ Adapter et
compa-nie . %2&2'

,n a donc '
JMF (Tous droits rservs) 18
!utoriau# pour les
AdapterView

Geaucoup de documentation e&iste pour les AdapterView

8ans la documentation .o##icielle., on a des tutoriau& sur ces composants +


partir de la d#inition de leur classe '

Spinner '
http://developer.android.com/guide/topics/ui/controls/
spinner.html

Gallery ' est, en #ait, dprcie + partir de l*AP 4:9 l #aut utiliser des
HorizontalScrollView et des ViewPager

GridEie< '
http://developer.android.com/guide/topics/ui/layout/gr
idview.html

%istEie< '
http://developer.android.com/guide/topics/ui/layout/li
stview.html
JMF (Tous droits rservs) 19
Spinner

(*est le composant graphi-ue Android similaire au (om2o 2o&


d*autres 2i2lioth-ues9 (*est un 2outon menu

Dn clic sur amne


JMF (Tous droits rservs) 20
Spinner " construction de
lIHM %1&3'

%es tapes sont '

4K) rcuprer le composant Spinner du #ichier d*!M

7K) construire la liste des items

?K) crer l*adapter associ + cette liste

LK) associer l*adapter au Spinner

A partir de
4K) est o2tenu par
<Spinner
android:id="@+id/spnMusketeers"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="2dp"
/>
Spinner spnMusketeers = (Spinner) findViewById(R.id.spnMusketeers);
JMF (Tous droits rservs) 21
Spinner " construction de
lIHM %2&3'

7K) construire la liste des items est o2tenu par '

?K) crer l*adapter associ + cette liste est o2tenu par '

0emar-ue ' %e #ormat


android.R.layout.simple_spinner_item est un #ormat
donn par la 2i2lioth-ue d*Android9 (e n*est pas un #ichier d*!M de
l*application9 8*ailleurs il n*y a pas android.R pour les #ichiers $M%
d*une application mais simplement R.
List<String> lsMusketeers = new ArrayList<String>();
lsMusketeers.add("Athos");
lsMusketeers.add("Porthos");
lsMusketeers.add("Aramis");
ArrayAdapter<String> aspnMusketeers =
new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,lsMusketeers);
JMF (Tous droits rservs) 22
Spinner " construction de
lIHM %3&3'

%e code prcdent #ait apparaMtre '


(e n*est pas 2ien 2eau N ,n aCoute plut"t
pour avoir

0emar-ue ' android.R.layout.simple_spinner_dropdown_item


est aussi un #ormat donn par la 2i2lioth-ue Android

LK) associer l*adapter au Spinner est o2tenu par '


aspnMusketeers.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spnMusketeers.setAdapter(aspnMusketeers);
JMF (Tous droits rservs) 23
Spinner " -estion des
vnements

%e listener associ + un Spinner est un OnItemSelectedListener (et


pas un OnClickListener)

Otre un ItemSelectedListener ncessite de donner un corps + deu&


mthodes '
public void onItemSelected (AdapterView<?> parent, View
view, int position, long id)
avec
parent ' l*AdapterView sur le-uel l*interaction s*est produite
view ' le composant graphi-ue dans l*AdapterView -ui a t slectionn
position ' l*indice de view dans l*AdapterView
id ' l*identi#icateur de l*item slectionn
est la mthode invo-ue -uand un item du Spinner est slectionn9 Elle
est invo-ue seulement si un nouveau choi& a t #ait

0emar-ue ' parent.getItemAtPosition(position) retourne la


donne associe + l*item slectionn
JMF (Tous droits rservs) 24
Spinner " le code complet

source ' P?Q page 4R6


Spinner spnMusketeers = (Spinner) findViewById(R.id.spnMusketeers);
// Positionne les items du Spinner
List<String> lsMusketeers = new ArrayList<String>();
lsMusketeers.add("Athos");
lsMusketeers.add("Porthos");
lsMusketeers.add("Aramis");
ArrayAdapter<String> aspnMusketeers =
new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,lsMusketeers);
aspnMusketeers.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spnMusketeers.setAdapter(aspnMusketeers);
// gestion des vnements
spnMusketeers.setOnItemSelectedListener(
new OnItemSelectedListener() {
public void onNothingSelected(AdapterView<?> arg0) { }
public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
// code appel lorsqu'un item est slectionn
String obj = (String)parent.getItemAtPosition(position);
Toast leToast = Toast.makeText(AdapterProjetActivity.this,
"item slectionn : " + obj, Toast.LENGTH_LONG);
leToast.show();
}
});
JMF (Tous droits rservs) 25
Gallery

Sait apparaMtre ses lments comme des ta2leau& dans une gallerie
(d*art)

%e d#ilement des items est hori3ontal

%*lment principal est centr et ses voisins


.en arrire plan.

Est un Spinner particulier '

Eoir dmo proCet !elloGallery

source ' P?Q page 4RT


JMF (Tous droits rservs) 26
Les items dune Gallery

(omme une Gallery est un AdapterView, les items d*une


Gallery sont #ournis par un Adapter9 (omme les lments d*une
Gallery ne sont pas des String, on utilise pour cela la classe
a2straite android.widget.BaseAdapter

,n indi-ue le composant graphi-ue #a2ri-u pour le position


ime lement de l*adapter par la mthode
public View getView (int position, View
convertView, ViewGroup parent) oI position est le
numro (commenUant + 0) de l*lment dans l*adapter

Pour une Gallery, la prsentation .image slectionn centre, les


voisines en arrire plan. est donn par une proprit Android
Theme_galleryItemBackground9 l #aut positionner cette valeur
pour cha-ue image cre pour cha-ue item

source ' P?Q


JMF (Tous droits rservs) 27
Gallery " le code %1&/'

l #aut dC+ avoir un ensem2le d*images N (+ dposer dans


res/drawable)

%e #ichier !M (res/layout/main.xml) contient '

%*activit -ui a##iche la Gallery a essentiellement pour code '


<?xml version="1.0" encoding="utf-8"?>
<Gallery xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gallery"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
public class HelloGallery extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Gallery gallery = (Gallery) findViewById(R.id.gallery);
gallery.setAdapter(new MonImageAdapter(this));
// ... pour un listener
}
}
JMF (Tous droits rservs) 28
Gallery " le code %2&/'

%*adapter associ + la Gallery est donc un o2Cet de la classe


MonImageAdapter

Pour placer cha-ue item de la Gallery, il #aut prciser un layout9


,n utilise le placement prd#ini galleryItemBackground9 ,n a
alors le #ichier res/values/attrs.xml -ui dcrit l*a##ichage des
items

%a classe MonImageAdapter commence comme '


<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="HelloGallery">
<attr name="android:galleryItemBackground" />
</declare-styleable>
</resources>
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
private Integer[] mImageIds = {
R.drawable.sample_1, ...
};
JMF (Tous droits rservs) 29
Gallery " le code %3&/'

%a classe MonImageAdapter continue par son constructeur '

%e conte&te c est ncessaire pour d*autres mthodes de la classe

Dn android.content.res.TypedArray un ensem2le de valeur


de type de style9 ,n rcupre celle associe au style .gallery item
pour l*application. et on la positionne dans la donne mem2re
mGalleryItemBackground

l est conseill de touCours appeler recycle() sur un TypedArray


pour une ventuelle rutilisation (c*est pas le cas ici mais 2on /1))
public MonImageAdapter(Context c) {
mContext = c;
TypedArray attr = mContext.obtainStyledAttributes(R.styleable.HelloGallery);
mGalleryItemBackground = attr.getResourceId(
R.styleable.HelloGallery_android_galleryItemBackground, 0);
attr.recycle();
}
JMF (Tous droits rservs) 30
Gallery " le code %0&/'

%ors-u*on construit son propre Adapter comme ici notre


MonImageAdapter pour un AdapterView, il #aut indi-uer le
composant graphi-ue -ui sera a##ich comme position ime item
de cet AdapterView9 (eci est indi-u + l*aide de la mthode
View getView(int position, ...) -ui retourne un tel
composant graphi-ue

(ette mthode getView() est appele automati-uement par


l*envirionnment d*e&cution et retourne la View pour l*item d*indice
position
JMF (Tous droits rservs) 31
Gallery " le code %1&/'

Eoici la mthode getView() pour la classe MonImageAdapter '

Ele construit une ImageView + partir des images dans


res/drawable, indi-ue la taille de cette image 4V;&4;; pi&els,
prcise -ue l*image originelle doit Atre tout entire contenue dans ce
rectangle 4V;&4;; (FIT_XY), positionne un #ond chatoyant pour
une image, 2re# un cadre (par mGalleryItemBackground)9 Elle
retourne en#in cette ImageView
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = new ImageView(mContext);
imageView.setImageResource(mImageIds[position]);
imageView.setLayoutParams(new Gallery.LayoutParams(150, 100));
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setBackgroundResource(mGalleryItemBackground);
return imageView;
}
JMF (Tous droits rservs) 32
Gallery " le code %/&/'

l #aut donner un corps au& mthodes getCount(), getItem(),


getItemId() -ui sont a2straites dans la classe de 2ase
BaseAdapter, d*oI leur code '

Huestion )ava ' pour-uoi return un int convient pour retourner un


Object dans la mthode getItem() J
public int getCount() {
return mImageIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}

0ponse ' c*est l*auto2o&ing de )ava 49V, un o2Cet .enveloppe.


Integer est #a2ri-u + partir de l*int et est retourn
JMF (Tous droits rservs) 33
Interaction sur une
Gallery

,n gre les interactions utilisateurs sur une Gallery + l*aide d*un


OnItemClickListener9 %e code d*interaction peut Atre '

%a mthode
public void onItemClick (AdapterView<?> parent,
View view, int position, long id) + implmenter a pour
arguments '

parent ' l*AdapterView -ui a reUu le clic de l*utilisateur

view ' la View -ui a reUu le clic

position ' l*indice de cette View dans l*adapter

id ' l*identi#iant de la View -ui a reUu le clic


gallery.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id) {
Toast.makeText(HelloGallery.this, "" + position, Toast.LENGTH_SHORT).show();
}
});
JMF (Tous droits rservs) 34
GridView

Sait apparaMtre ses lments dans une grille (ta2leur) ligne1colonne

%e d#ilement des items est hori3ontal ou vertical

%*ar2orescence des classes est '

8mo proCet !elloGridEie<


JMF (Tous droits rservs) 35
GridView " le code %1&2'

l est similaire + celui de la Gallery

%e #ichier !M (res/layout/main.xml) est '

%a classe MonImageAdapter commence par '


<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gridview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:columnWidth="90dp"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center"
/>
public class MonImageAdapter extends BaseAdapter
{
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
JMF (Tous droits rservs) 36
GridView " le code %2&2'

%a mthode getView() est '


// Cr une ImageView pour chaque item rfrenc dans l'Adapter
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
// si ConvertView n'a pas t rcupr, construire une ImageView
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageResource(mThumbIds[position]);
return imageView;
}
JMF (Tous droits rservs) 37
Le composant ListView

.A (%ist)vie< (that) sho<s items in a vertically scrolling


list9 The items come #rom the ListAdapter associated
<ith this vie<9. (W)

Par#ois les items proviennent d*un accs distant

!ritage de ListView '

Dne ListView est donc un AdapterView -ui est


.a vie< <hose children are determined 2y an Adapter9. (WW)

sources ' (W)


http://developer.android.com/reference/android/widget/ListView.html
(WW)
http://developer.android.com/reference/android/widget/AdapterView.ht
ml
JMF (Tous droits rservs) 39
Le composant ListView

l permet d*a##icher une (grande) liste d*items, accessi2le par d#ilement


mais aussi par #iltre ' l*utilisateur tape les premires lettres, le ListView
n*a##iche plus -ue les items -ui commencent par ces lettres

Pour d#inir un ListView, on commence par indi-uer comment sera


a##ich cha-ue item du ListView9 Par e&emple sous #orme de
TextView9 ,n construit donc le #ichier res/layout/list_item.xml '

Dne dmo ' proCet !ello%istEie<


<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:textSize="16sp" >
</TextView>
JMF (Tous droits rservs) 40
Lactivit ListActivity

Dne ListView peut occuper tout l*cran9 8ans ce cas, elle peut Atre
construite + partir d*une android.app.ListActivity (-ui hrite de
android.app.Activity)

%ors-u*on construit une classe -ui hrite de ListActivity, on peut


alors utiliser plusieurs mthodes de la classe ListActivity '

public ListView getListView() -ui retourne le composant


graphi-ue ListView associ + cette activit

public void setListAdapter(ListAdapter adapter)


positionne le ListAdapter associ + la ListView de cette activit
ListActivity

Et on spcialise la mthode onCreate() (comme d*ha2) et on a une


Activity -ui prsente une ListView
JMF (Tous droits rservs) 41
ListView " 1er e#emple 2
laide de ListActivity'
public class HelloListViewActivity extends ListActivity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, COUNTRIES));
ListView lv = getListView();
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// le code lanc lors de la slection d'un item
}
});
}
static final String[] COUNTRIES = new String[] { ... }
}
JMF (Tous droits rservs) 42
ArrayAdapter<T> pour
ListView

,n construit le ListAdapter + partir d*un


ArrayAdapter<String>9 En #ait on a l*ar2orescence
(d*inter#aces, de classe a2straite et de classe
gnri-ue N) suivante '

,n a utilis le constructeur '


public ArrayAdapter (Context context,
int textViewResourceId,
T[] objects)
car '
Activity drive de Context '
textViewResourceId repre l*!M -ui modlise un
item
objects est le ta2leau de donnes + a##icher

%a ListView construite + partir de l*activit et rcupre


par getListView(), est sensi2le + la slection par
pr#i&e grXce + l*appel
setTextFilterEnabled(true);
JMF (Tous droits rservs) 43
2i+me e#emple " utiliser une
ListView dans une Activity

Dne ListView peut Atre construite + partir d*une Activity (et pas
d*une ListActivity)

8mo ' Eeli2ProCet


JMF (Tous droits rservs) 44
3tiliser une ListView dans
une Activity

%a ListView est indi-ue dans un #ichier $M% d*!M

8ans le code )ava, on rcupre cette ListView (par la mthode miracle


findViewById()) et on l*alimente d*items par '
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView android:layout_height="wrap_content"
android:layout_width="match_parent" android:id="@+id/listMenu">
</ListView>
</LinearLayout>
ListView laListe = (ListView) findViewById(R.id.listMenu);
Resources res = getResources();
String [] lesItems = new String[] {
res.getString(R.string.seeAllStations),
res.getString(R.string.aboutUs)
};
laListe.setAdapter(new ArrayAdapter<String>(this, R.layout.list_item, lesItems));

seeAllStations et aboutUs, 999 ont d#inies dans


res/values/strings.xml
JMF (Tous droits rservs) 45
ListView " la -estion des
vnements

%a gestion des vnements est assur par l*auditeur


public void setOnItemClickListener
(AdapterView.OnItemClickListener listener)

AdapterView.OnItemClickListener est une inter#ace -ui demande


d*implmenter la mthode
public void onItemClick(AdapterView<?> parent, View view, int
position, long id)
-ui est lance lors-ue l*utilisateur slectionne un item de la ListView
parent est l*AdapterView -ui a t utilis lors de l*vnement
view est la View (c*est + dire l*item a l*intrieur de la ListView) -ui a t
utilis
position est le numro de l*item dans cette ListView9 %a valeur 0 est celle
du premier item
id est l*identi#icateur de l*item slectionn
JMF (Tous droits rservs) 46
3ne 4uestion 5ava

Pour-uoi la mthode
public void setOnItemClickListener
(AdapterView.OnItemClickListener listener)
-ui demande comme argument un AdapterView.OnItemClickListener peut
Atre utilis par le code '
lv.setOnItemClickListener(new OnItemClickListener() { ... });
J

0ponse ' (ar Eclipse aCoute, aprs S!ST Y (T0% Y ,, le 2on import
import android.widget.AdapterView.OnItemClickListener;

Merci Sa2rice N
JMF (Tous droits rservs) 47
6#ercice

(onstruire une activit prsentant un ListView (4re tape)

Grer les a##ichages de l*cran suivant le choi& de l*utilisateur des


di##rents items de cette ListView (7ime tape)
JMF (Tous droits rservs) 48
Afficher des ob7ets dans une
ListView

,n a une collection d*o2Cets, on voudrait les a##icher .Coliment. dans une


ListView

Par e&emple une liste d*DE constituant un dipl"me

Dne dmo ' ProCet (erti#(ompet, onglet


.Dnits d*enseignement.

l s*agit de #aire a##icher une ArrayList<UE>


avec
constituant un dipl"me
public class UE {
private String nom, lieu, periode;
...
}
public class DiplomeCNAM {
private ArrayList<UE> lesUE;
public DiplomeCNAM() {
this.lesUE = new ArrayList<UE>();
...
}
public ArrayList<UE> getLesUE() {return lesUE; }
}
JMF (Tous droits rservs) 49
Adapteur dob7ets pour une
ListView

,n construit un Adapter pour la ListView en drivant de


BaseAdapter

l #aut donc donner un corps au& mthodes a2straites des classes


ancAtres '
public class LeBelAdapter extends BaseAdapter {
private DiplomeCNAM diplome;
...
public int getCount() {
return diplome.getLesUE().size();
}
public Object getItem(int position) {
return diplome.getLesUE().get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
// Dtaill plus loin
}
}
JMF (Tous droits rservs) 50
LIHM de cha4ue item %1&3'

(omme d*ha2itude, l*!M de cha-ue item est dcrit par le #ichier


res\layout\uecnam.xml '

8*a2ord un TextView de taille 4:sp


<?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:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:text="TextView" />

JMF (Tous droits rservs) 51
LIHM de cha4ue item %2&3'

Puis un TableRow -ui #onctionne comme un LinearLayout hori3ontal


<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/imageId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/orange01" >
>
</ImageView>
<TextView
android:id="@+id/lieuId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="12sp" >
</TextView>
</TableRow>
</LinearLayout>
JMF (Tous droits rservs) 52
LIHM de cha4ue item %3&3'

%e TableRow contient une ImageView et un TextView

%*ImageView contient l*image orange01 comme valeur par d#aut

%e TextView contient Te&tEie< comme te&te par d#aut

%*apparence du te&te est l*apparence standard de l*AP Android,


textAppearanceMedium -ui est d#ini par le #ichier platforms\android-
X\data\res\values\themes.xml du sdB -ui contient '
-ui redirige en #ait sur \platforms\android-
X\data\res\values\styles.xml -ui contient '

source ' http://stackoverflow.com/questions/11590538/dpi-value-of-


default-large-medium-and-small-text-views-android
<item name="textAppearanceLarge">@android:style/TextAppearance.Large</item>
<item name="textAppearanceMedium">@android:style/TextAppearance.Medium</item>
<item name="textAppearanceSmall">@android:style/TextAppearance.Small</item>
<style name="TextAppearance.Medium">
<item name="android:textSize">18sp</item>
<item name="android:textStyle">normal</item>
<item name="android:textColor">?textColorPrimary</item>
</style>
JMF (Tous droits rservs) 53
La mthode getView() de
ladapteur %1&2'

(*est cette mthode -ui construit la View de cha-ue item de la


ListView

,n peut l*crire ainsi '


public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = null;
inflater = (LayoutInflater)
ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.uecnam, parent, false);
TextView nomView = (TextView)itemView.findViewById(R.id.textView1);
ImageView imageView = (ImageView)itemView.findViewById(R.id.imageId);
TextView lieuView = (TextView)itemView.findViewById(R.id.lieuId);
nomView.setText(diplome.getLesUE().get(position).getNom());
lieuView.setText(diplome.getLesUE().get(position).getLieu());
String periode = diplome.getLesUE().get(position).getPeriode();
if (periode.equals("1")) {
imageView.setImageResource(R.drawable.orange01);
} else {
imageView.setImageResource(R.drawable.green02);
}
return itemView;
}
JMF (Tous droits rservs) 54
La mthode getView() de
ladapteur %2&2'

(ette mthode rcupre l*analyseur $M% (un LayoutInflater) de


#ichier d*!M, puis chacun des composants graphi-ues et positionne avec
des valeurs prcises #onction du numro de l*item dans la %istEie<
associe + cet adapteur

,n a donc un e&emple de construction graphi-ue en partie stati-ue (+


l*aide d*un #ichier $M%) pour les valeurs gnrales, et en partie
dynami-ue (+ l*aide de la programmation) pour les parties varia2les
JMF (Tous droits rservs) 55
3n cache pour la
construction des items

%e pro2lme avec l*criture de getView() prcdente est -ue cette


mthode est lance pour cha-ue item

Et donc l*analyse $M% du #ichier d*!M est #aite pour cha-ue item 999

alors -ue cela donne touCours le mAme rsultat N

%es parties de programmation communes doivent Atre #aites -u*une


seule #ois

,n utilise un cache '


class CacheView {
private TextView nomView;
private ImageView imageView;
private TextView lieuView;
// accesseurs set/get pour ces champs
...
}
JMF (Tous droits rservs) 56
Le fonctionnement dune
List8ie9

Dne %istEie< garde trace des Eie< de cha-ue item dC+ construit9 (*est une
rserve de .ScrapEie<. '
.ScrapEie<s are old vie<s that could potentially 2e used 2y the adapter to avoid
allocating vie<s
unnecessarily. (https://github.com/android/platform_frameworks_b
ase/blob/43ee0ab8777632cf171b598153fc2c427586d332/core/java/
android/widget/AbsListView.java#L5764)

source ' http://lucasr.org/2012/04/05/performance-tips-for-


androids-listview/
JMF (Tous droits rservs) 57
Association de donnes 2
une View

,n peut donc rutiliser si possi2le les ScrapEie<s

%ors-ue getView() est lanc, l*argument convertView repre


ventuellement une ScrapEie< -ui correspond + l*item + a##icher9 Si c*est
le cas, inutile de re#re l*analyse $M%9 Si ce n*est pas le cas, on construit
la vue de cet item et on lui associe des donnes particulires

,n associe des donnes supplmentaires + une View + l*aide de sa


mthode public void setTag (Object tag) (de la classe View)

,n rcupre des donnes supplmentaires + une View + l*aide de sa


mthode public Object getTag() (de la classe View)

l su##it alors, la #ois suivante, si on a rcuprer une ScrapEie< pour


l*tem, de rechercher ces donnes
JMF (Tous droits rservs) 58
Rcriture de getView()

8*ou le code .optimis. de getView() (et merci Cean1michel)


public View getView(int position, View convertView, ViewGroup parent) {
View itemView = convertView;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater)
ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
itemView = inflater.inflate(R.layout.uecnam, parent, false);
CacheView cache = new CacheView();
cache.setNomView((TextView)itemView.findViewById(R.id.textView1));
cache.setImageView((ImageView)itemView.findViewById(R.id.imageId));
cache.setLieuView((TextView)itemView.findViewById(R.id.lieuId));
itemView.setTag(cache);
}
CacheView cache = (CacheView)itemView.getTag();
cache.getNomView().setText(diplome.getLesUE().get(position).getNom());
cache.getLieuView().setText(diplome.getLesUE().get(position).getLieu());
String periode = diplome.getLesUE().get(position).getPeriode();
if (periode.equals("1")) {
cache.getImageView().setImageResource(R.drawable.orange01);
} else {
cache.getImageView().setImageResource(R.drawable.green02);
}
return itemView;
}
JMF (Tous droits rservs) 59
La :3I !hread:

8ans une application Android, il e&iste une et une seule thread -ui
gre l*inter#ace graphi-ue ' la D Thread (Dser nter#ace Thread)

.There is one main application thread (.D thread.) per process,


supporting all activities, services, and 2roadcast receivers in that
process., MarB Murphy auteur de .The Gusy (oder*s Guide to
Android 8evelopment.

Tout ce -ui concerne l*a##ichage est (et doit Atre) gr par cette
Thread9 Si une autre Thread s*occupe de #aire de l*a##ichage
graphi-ue, il y a erreur + l*e&cution

%ors-u*un travail demandant du temps est lanc, il #aut le #aire dans


une Thread autre -ue la D Thread9 Au 2esoin en cr une N

Au lieu de crer de telles threads et de les grer, Android propose


une classe -ui gre correctement cela9 (*est la classe (gnri-ue N)
android.os.AsyncTask<Params, Progress, Result>
JMF (Tous droits rservs) 60
La classe
android.os.AsyncTask<Params, Progress, Result>

Elle est #aite pour grer correctement la gestion entre une thread
(de traitement long) et la D Thread

Elle permet de lancer un traitement en arrire plan et de mettre +


Cour (ventuellement de temps en temps) l*inter#ace graphi-ue de
l*application

%es paramAtres gnri-ues sont utiliss pour '

Params ' le type des paramAtres ncessaires + la tXche en


arrire plan

Progress ' le type de paramAtre reUus par la mthode de mise


+ Cour

Result ' le type de rsultat retourn par la tXche en arrire


plan
JMF (Tous droits rservs) 61
Les mthodes de
AsyncTask<Params, Progress, Result>

(ette classe contient L mthodes dont trois d*entre elles sont e&cutes
dans la D Thread9 (e sont ' onPreExecute(),
onProgressUpdate(Progress...), onPostExecute(Result) -ui
sont e&cutes dans la D Thread et doInBackground(Params...) lanc
dans une autre thread

onPreExecute() est e&cut avant le lancement de la tXche d*arrire plan

doInBackground(Params...) est lanc aprs onPreExecute() dans


une thread autre -ue la D Thread ' c*est le traitement en arrire plan9 %es
paramAtres de type Params sont passs + cette mthode9 (ette mthode
retourne un resultat de type Result (-ui sera e&ploit par
onPostExecute(Result))9 (ette mthode peut lancer
publishProgress(Progress...) -ui permet de lancer
onProgressUpdate(Progress...) dans la D Thread et mettre ainsi +
Cour l*!M de l*application, tout en continuant la tXche en arrire plan

onPostExecute(Result) est lanc aprs la #in de la tXche en arrire


plan9 (ette mthode reUoit le paramAtre de type Result -u*a renvoy
doInBackground(Params...)
JMF (Tous droits rservs) 62
3tilisation de
AsyncTask<Params, Progress, Result>

Pour utiliser cette classe, il #aut la sous classer, construire une instance de
cette sous1classe et lancer la mthode de type execute(Params ...) sur
cette instance

l #aut au moins red#inir la mthode doInBackground(Params...) (2on


sens N)

%a sous classe cre est souvent une sous1classe interne + une mthode

%a cration de l*instance de cette sous classe doit Atre #aite dans la D


Thread et execute(Params ...) doit Atre lance sur cette instance une
seule #ois dans la D Thread

%es mthodes onPreExecute(), doInBackground(Params...),


onProgressUpdate(Progress...), onPostExecute(Result) ne
doivent pas Atre lances e&plicitement ' c*est la mthode execute() -ui
dclenche le tout
JMF (Tous droits rservs) 63
6#emple de code de
AsyncTask<Params, Progress, Result>
class ChargementDesStationsTache extends AsyncTask<String, String, String> {
protected void onPreExecute() {
progress = ProgressDialog.show(ListingDesStationsActivity.this,
getResources().getString(R.string.app_name),
getResources().getString(R.string.chargement_message),
true);
}
protected String doInBackground(String ... urls) {
// charger les stations
try {
sp = new StationsParser(getBaseContext());
} catch (Exception e) { e.printStackTrace(); }
leStationsAdapter = new StationsAdapter(getBaseContext(),
ListingDesStationsActivity.this, sp.getArrList()) ;
return null;
}
protected void onProgressUpdate(String... aAfficher) { }
protected void onPostExecute(String result) {
// arrter le progressDialog
progress.dismiss();
// mettre jour la ListView des stations
listing.setAdapter(leStationsAdapter);
}
}
new ChargementDesStationsTache().execute();
JMF (Tous droits rservs) 64
Confi-uration de
lAndroidManifest.xml

(omme l*application demande + utilliser l*internet, il #aut l*indi-uer dans le


#ichier AndroidManifest.xml par '
<uses-permission android:name="android.permission.INTERNET" />
#ils de l*lment manifest

(omme l*application demande + utiliser une nouvelle Activity, il #aut


l*indi-uer dans le #ichier AndroidManifest.xml par '
<activity android:name=".ListingDesStationsActivity" />
#ils de l*lment application

Par e&emple '


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android=... >
...
<uses-permission android:name="android.permission.INTERNET" />

<application ...
...
<activity android:name=".ListingDesStationsActivity" />
</application>
</manifest>
JMF (Tous droits rservs) 65
6#ercice

Ecrire une activit contenant une ListView alimente par des


donnes se trouvant + une D0%
JMF (Tous droits rservs) 66
;iblio-raphie pour ce
chapitre

P4Q ' Pour ce chapitre


http://developer.android.com/guide/topics/ui/index.html

P7Q ' The Gusy (oder*s Guide to Android 8evelopment, MarB %9


Murphy / editions (ommonsZare

P?Q ' Android Application 8evelopment, 0icB 0ogers, )ohn


%om2ardo, [igurd MednieBs and GlaBe MeiBe / editions ,*0eilly, 7;;R

Pour l*optimisation de %istEie< ' polycopi de cours


%istEie<\ntroduction de )ean1Michel 8ouin et
http://lucasr.org/2012/04/05/performance-tips-for-
androids-listview/
JMF (Tous droits rservs) 67
,in

Вам также может понравиться