Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pdm:laboratoare:04 [2016/03/18 23:30]
127.0.0.1 external edit
pdm:laboratoare:04 [2016/03/20 23:56] (current)
alexandru.radovici
Line 1: Line 1:
-===== Laboratorul 04. =====+====== Laborator 4 - Liste ====== 
 + 
 +In aplicatiile realizate, un element important pe care il vom utiliza il reprezinta listeleSub 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. {{ :​laboratoare:​640px-list_adapter.png |}} 
 + 
 +===== ListView ===== 
 + 
 +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. 
 + 
 +===== ListActivity ===== 
 + 
 +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: <​html><​code java></​html>​%%//​%% 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 ();<​html></​code></​html>​ 
 + 
 +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. <​html><​code java></​html>​ @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)%%''​\\ 
 +''​%%   }%%''<​html></​code></​html>​ 
 + 
 +===== ListAdapter ===== 
 + 
 +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 . 
 + 
 +==== ArrayAdapter ==== 
 + 
 +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: <​html><​code java></​html>​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%%''<​html><​Personaj></​html>''​%% personaje;​%%''​\\ 
 +''​%%   ArrayAdapter%%''<​html><​Personaj></​html>''​%% adapter;​%%''​\\ 
 +\\ 
 +''​%%   @Override%%''​\\ 
 +''​%%   public void onCreate (Bundle savedInstanceBundle)%%''​\\ 
 +''​%%   {%%''​\\ 
 +''​%%       super.onCreate (savedInstanceBundle);​%%''​\\ 
 +''​%%       personaje = new ArrayList%%''<​html><​Personaj></​html>''​%%();​%%''​\\ 
 +''​%%       adapter = new ArrayAdapter%%''<​html><​Personaj></​html>''​%%(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();​%%''​\\ 
 +''​%%   }%%''​ 
 + 
 +}<​html></​code></​html>​ 
 + 
 +==== Exercitii ==== 
 + 
 +  - Realizati o lista (editabila) cu personaje din desene animate. Pe activitate veti avea posibilitatea de a adauga un personaj in lista. Stergerea se va face prin apasarea lunga ( sau ) pe un element din lista. 
 + 
 +==== BaseAdapter ==== 
 + 
 +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: <​html><​code java></​html>​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%%''​\\ 
 +''​%%   }%%''​ 
 + 
 +}<​html></​code></​html>​ 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 <​html><​code xml></​html>​ 
 + 
 +<​HTML>​ 
 +<?xml version="​1.0"​ encoding="​utf-8"?>​ 
 +</​HTML>​ 
 +<​html><​LinearLayout 
 +  xmlns:​android="​http://​schemas.android.com/​apk/​res/​android"​ 
 +  android:​layout_width="​fill_parent"​ 
 +  android:​layout_height="​fill_parent"​ 
 +  android:​orientation="​vertical"></​html>​ 
 + 
 +''​%%   %%''<​html><​TextView android:​id="​@+id/​personaj_nume"​ 
 +         ​android:​layout_width="​fill_parent"​ 
 +         ​android:​layout_height="​wrap_content"​ 
 +         ​android:​textStyle="​bold"/></​html>​\\ 
 +\\ 
 +''​%%   %%''<​html><​TextView android:​id="​@+id/​personaj_desen"​ 
 +         ​android:​layout_width="​fill_parent"​ 
 +         ​android:​layout_height="​wrap_content"/></​html>​ 
 + 
 +<​html></​LinearLayout></​code></​html>​ Urmeaza sa realizam fisierul cu codul sursa. Acesta va contine o clasa ce extinde ​ si clasa activitatii (). <​html><​code java></​html>​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%%''<​html><​Personaj></​html>''​%% personaje;​%%''​\\ 
 +\\ 
 +''​%%   public PersonajeAdapter (Activity _context)%%''​\\ 
 +''​%%   {%%''​\\ 
 +''​%%       this.context = _context;​%%''​\\ 
 +''​%%       personaje = new ArrayList%%''<​html><​Personaj></​html>''​%%();​%%''​\\ 
 +''​%%   }%%''​\\ 
 +\\ 
 +''​%%   @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%%''<​html><​Personaj></​html>''​%% personaje;​ ->​ mutat in PersonajeAdapter%%''​\\ 
 +''​%%   PersonajeAdapter adapter;​%%''​\\ 
 +\\ 
 +''​%%   @Override%%''​\\ 
 +''​%%   public void onCreate (Bundle savedInstanceBundle)%%''​\\ 
 +''​%%   {%%''​\\ 
 +''​%%       super.onCreate (savedInstanceBundle);​%%''​\\ 
 +''​%%       //​ personaje = new ArrayList%%''<​html><​Personaj></​html>''​%%();​ ->​ 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();​%%''​\\ 
 +''​%%   }%%''​ 
 + 
 +}<​html></​code></​html>​ Sunt importante urmatoarele observatii:​ 
 + 
 +  * modelul () a fost mutat in adaptor. Acesta este de fapt legatura intre lista si date, deci el este cel care trebuie sa cunoasca datele, si nu fereastra 
 +  * implementarea functiei ​ nu este eficienta, nu este folosit parametrul . 
 +  * setarea actiunii pentru click-ul lung se face direct pe lista, nu exista o functie in  ce sa poata fi suprascrisa 
 + 
 +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. <​html><​code java></​html>​@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;​%%''​\\ 
 +''​%%   }%%''<​html></​code></​html>​ 
 + 
 +==== Exercitii ==== 
 + 
 +  - Realizati o lista mai complexa pentru afisarea personajelor din desene animate. Pe fereastra veti avea posibilitatea de a introduce un nou personaj. Nu folositi parametrul ! Fiecare personaj contine: 
 +    * Nume 
 +    * Desenul animat din care face parte 
 +    * O poza (poza va fi aleasa in functie de butonul de adaugare apasat) 
 +  - Modificati problema precedenta, folosind , insa setati valorile View-urilor doar la creare. (In alte cuvinte, daca , pur si simplu il intoarceti, fara sa il modificati.) Observati ce se intampla. 
 +  - Modificati problema precedenta, folosind corespunzator . 
 +  - Optimizati lista de la exercitiul precedent, folosind tag-ul View-urilor.
  
  
pdm/laboratoare/04.1458336642.txt.gz · Last modified: 2016/03/20 23:56 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0