In aplicatiile realizate, un element important pe care il vom utiliza il reprezinta listele. Sub platforma Android, acestea sunt implementate folosind modelul MVC (Model View Controller). Modelul este reprezentat de datele ce trebuie afisate, View-ul este lista propriu-zisa si Controller-ul este programul care controleaza modul de afisare.
Un este un View care contine o lista de elemente, care poate fi parcursa. Un View de tip poate fi plasat pe orice tip de activitate. In mod normal, descriem ListView-ul in fisierul xml atasat activitatii, ii dam un id si in codul java luam un pointer catre el.
Exista un mod mai simplu decat folosirea unui . In general, pe o activitate exista o singura lista, astfel ca Android ne pune la dispozitie un tip special de activitate, numit , care rezolva automat preluarea pointer-ului listei. In XML, trebuie declarat obligatoriu un cu id-ul . De asemenea, ListActivity pune la dispozitie urmatoarele functii: // seteaza adaptorul pentru lista de pe fereastra void setListAdapter (ListAdapter adapter);
// intoarce adaptorul listei de pe fereastra ListAdapter getListAdapter ();
// intoarce un pointer catre lista din fereastra ListView getListView ();
O alta functie oferita de catre ListActivity este onListItemClick(). Acesta este apelata automat de fiecare data cand se executa un click asupra unui element din lista. Initial functia este vida, in alte cuvinte, nu face nimic. Pentru a-i adauga o actiune, programatorul trebuie sa suprascrie acesta functie. @Override
public void onListItemClick (ListView list, View v, int position, long id)
{
// list - este lista de pe fereastra
// v - este elementul din lista pe care s-a dat click
// position - este pozitia pe care s-a dat click (de fapt pozitia la care se afla elementul v in lista)
// id - este id-ul elementului (obtinut prin functia getItemId () a adaptorului)
}
In Android, lista este de fapt un vertical. Sarcina programatorului este de fapt crearea componentelor View pentru fiecare linie din acest , adica crearea unui element pe ecran pentru fiecare element pe care dorim sa il introducem in lista. In alte cuvinte, daca ne uitam la poza de mai sus, ceea ce trebuie noi sa facem este sa scriem componenta . Din punct de vedere ar programarii, asta inseamna crearea unui obiect care sa implementeze interfata . Biblioteciile Android ne pun la dispozitie mai multe variante de a implementa .
Pentru liste simple, ce contin elemente cu o singura linie de text se poate folosi o clasa mult simplificata, si anume . Acesta presupune ca toate elementele sunt stocate intr-un sir (ex: Object[]) sau o lista (orice obiect ce implementeaza interfata ). Deoarece fiecare element din lista este o linie de text si in sir sau lista noi pastram obiecte, adaptorul va apela functia pe fiecare obiect. Un exemplu de folosire este urmatorul: class Personaj {
public String nume;
public String desen;
@Override
public String toString ()
{
// acesta functie este apelata de catre ArrayAdapter pentru a transforma obiectul intr-un String ce
// sa fie afisat in lista
return nume+" din desenul animat "+desen;
}
}
public class ListaDeseneAnimate extends ListActivity {
ArrayList
personaje;
ArrayAdapter
adapter;
@Override
public void onCreate (Bundle savedInstanceBundle)
{
super.onCreate (savedInstanceBundle);
personaje = new ArrayList
();
adapter = new ArrayAdapter
(this, android.R.layout.simple_list_item_1, personaje);
setContentView (R.layout.main);
setListAdapter (adapter);
// adaugam cateva personaje in lista
adaugaFunnyGuy("Bugs Bunny", "Looney Toons");
adaugaFunnyGuy("Fred Flinstone", "The Flinstones");
adaugaFunnyGuy("Betty Rubble", "The Flinstones");
}
@Override
public void onListItemClick (ListView list, View v, int position, long id)
{
// afisam numele personajului pe care s-a dat click folosind un Toast
Toast.makeText(ListaDeseneAnimate.this, personaje.get(position).nume, Toast.LENGTH_LONG).show();
}
private void adaugaFunnyGuy (String nume, String desen)
{
Personaj p = new Personaj ();
p.nume = nume;
p.desen = desen;
personaje.add (p);
// acesta functie determina adaptorul sa ceara listei sa reafiseze continutul
adapter.notifyDataSetChanged();
}
}
Pentru o lista ce trebuie sa afiseze informatii mai complexe decat un rand de text, trebuie sa scriem un adaptor (o clasa ce implmenteaza interfata ). Pentru ca interfata are foarte multe metode, un mod mai simplu este sa extindem clasa . De fapt trebuie sa implementam urmatoarele patru functii: class MyAdapter extends BaseAdapter {
@Override
public View getView (int position, View convertView, ViewGroup list)
{
// functia trebuie sa intoarca view-ul de pe pozitia position din lista
// convertView este un element din lista ce nu mai este vizibil si poate fi convertit
}
@Override
public int getCount ()
{
// intoarce nr de elemente din lista
}
@Override
public Object getItem(int position)
{
// intoarce elementul de pe pozitia position din model
}
@Override
public long getItemId(int position)
{
// fiecare element din lista poate avea un id, nu este insa obligatoriu
}
} Pentru a exemplifica mai bine, vom modifica exemplul de mai sus, astfel incat sa afisam doua linii de text. Clasa Personaj ramane aceeasi ca in exemplul precedent. Primul pas este sa realizam un nou fisier XML (separat) ce va descrie cum arata fiecare element grafic (View) din lista. Il vom plasa in . personaj.xml
Urmeaza sa realizam fisierul cu codul sursa. Acesta va contine o clasa ce extinde si clasa activitatii (). class Personaj {
public String nume;
public String desen;
@Override
public String toString ()
{
// acesta functie este apelata de catre ArrayAdapter pentru a transforma obiectul intr-un String ce
// sa fie afisat in lista
return nume+" din desenul animat "+desen;
}
}
class PersonajeAdapter extends BaseAdapter {
private Activity context;
ArrayList
personaje;
public PersonajeAdapter (Activity _context)
{
this.context = _context;
personaje = new ArrayList
();
}
@Override
public View getView (int position, View convertView, ViewGroup list)
{
// functia trebuie sa intoarca view-ul de pe pozitia position din lista
// convertView este un element din lista ce nu mai este vizibil si poate fi convertit
View element;
LayoutInflater inflater = context.getLayoutInflater();
element = inflater.inflate(R.layout.personaj, null);
TextView nume = (TextView)element.findViewById(R.id.personaj_nume);
TextView desen = (TextView)element.findViewById(R.id.personaj_desen);
nume.setText(personaje.get(position).nume);
desen.setText(personaje.get(position).desen);
return element;
}
@Override
public int getCount ()
{
// intoarce nr de elemente din lista
return personaje.size ();
}
@Override
public Object getItem(int position)
{
// intoarce elementul de pe pozitia position din model
return personaje.get(position);
}
@Override
public long getItemId(int position)
{
// fiecare element din lista poate avea un id, nu este insa obligatoriu
return 0;
}
public void adaugaFunnyGuy (String nume, String desen)
{
Personaj p = new Personaj ();
p.nume = nume;
p.desen = desen;
personaje.add (p);
// acesta functie determina adaptorul sa ceara listei sa reafiseze continutul
this.notifyDataSetChanged();
}
}
public class ListaDeseneAnimate extends ListActivity {
// ArrayList
personaje; -> mutat in PersonajeAdapter
PersonajeAdapter adapter;
@Override
public void onCreate (Bundle savedInstanceBundle)
{
super.onCreate (savedInstanceBundle);
// personaje = new ArrayList
(); -> mutat in Personaje Adapter
adapter = new PersonajeAdapter (this);
setContentView (R.layout.main);
setListAdapter (adapter);
// adaugam cateva personaje in lista
adapter.adaugaFunnyGuy("Bugs Bunny", "Looney Toons");
adapter.adaugaFunnyGuy("Fred Flinstone", "The Flinstones");
adapter.adaugaFunnyGuy("Betty Rubble", "The Flinstones");
// pentru a seta actiunea click lung
getListView().setOnItemLongClickListener(new OnItemLongClickListener()
{
public boolean onItemLongClick(AdapterView<?> listAdapter, View view,
int position, long id)
{
Personaj p = (Personaj)adapter.getItem (position);
Toast.makeText(this, "click lung pe "+p.nume, Toast.LENGTH_LONG).show();
return true;
}
});
}
@Override
public void onListItemClick (ListView list, View v, int position, long id)
{
// afisam numele personajului pe care s-a dat click folosind un Toast
Personaj p = (Personaj)adapter.getItem (position);
Toast.makeText(this, p.nume, Toast.LENGTH_LONG).show();
}
} Sunt importante urmatoarele observatii:
Implementarea eficienta presupune folosirea parametrului . Acesta este fie , caz in care trebuie ignorat, fie un obiect intors aterior de catre , insa obiect care nu mai este vizibil. Ideea este ca, in loc de a crea un nou View de fiecare data, sa se refoloseasca View-urile create anterior si care nu mai sunt vizibile. @Override
public View getView (int position, View convertView, ViewGroup list)
{
// functia trebuie sa intoarca view-ul de pe pozitia position din lista
// convertView este un element din lista ce nu mai este vizibil si poate fi convertit
View element;
if (convertView == null)
{
LayoutInflater inflater = context.getLayoutInflater();
element = inflater.inflate(R.layout.personaj, null);
}
else element = convertView;
TextView nume = (TextView)element.findViewById(R.id.personaj_nume);
TextView desen = (TextView)element.findViewById(R.id.personaj_desen);
nume.setText(personaje.get(position).nume);
desen.setText(personaje.get(position).desen);
return element;
}