Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
laboratoare:laborator05 [2015/03/23 15:52] Andrei Roșu-Cojocaru |
laboratoare:laborator05 [2015/04/22 17:40] (current) Andrei Roșu-Cojocaru [Spinner] |
||
|---|---|---|---|
| Line 279: | Line 279: | ||
| android:dropDownVerticalOffset="10dp" | android:dropDownVerticalOffset="10dp" | ||
| android:popupBackground="@drawable/mobiledevice" | android:popupBackground="@drawable/mobiledevice" | ||
| - | android:dropDownSelector="@color/lightblue" /> | + | android:dropDownSelector="@color/lightblue" /> |
| </code> | </code> | ||
| </columns> | </columns> | ||
| - | {{ :laboratoare:laborator05:sample_spinner_dialog.png?nolink&500 }} | + | {{ :laboratoare:laborator05:sample_spinner_dialog.png?nolink&400 }} |
| - | {{ :laboratoare:laborator05:sample_spinner_dropdown.png?nolink&500 }} | + | {{ :laboratoare:laborator05:sample_spinner_dropdown.png?nolink&400 }} |
| Pentru un astfel de obiect vor trebui specificate două mecanisme de afișare a conținutului: | Pentru un astfel de obiect vor trebui specificate două mecanisme de afișare a conținutului: | ||
| Line 426: | Line 426: | ||
| </file> | </file> | ||
| - | {{ :laboratoare:laborator05:sample_gallery.png?nolink&500 }} | + | {{ :laboratoare:laborator05:sample_gallery.png?nolink&400 }} |
| ==== Tipuri de adaptoare pentru colecții de date ==== | ==== Tipuri de adaptoare pentru colecții de date ==== | ||
| Line 466: | Line 466: | ||
| - modificarea elementelor din sursa de date cu notificarea obiectului adaptor asociat prin intermediul metodei ''notifyDataSetChanged()'', astfel încât operațiile realizate asupra sursei de date să se propage și la nivelul controlului grafic care îi afișează conținutul. | - modificarea elementelor din sursa de date cu notificarea obiectului adaptor asociat prin intermediul metodei ''notifyDataSetChanged()'', astfel încât operațiile realizate asupra sursei de date să se propage și la nivelul controlului grafic care îi afișează conținutul. | ||
| - | <note tip>Metodele pentru modificarea colecției de date prin intermediul obiectului de tip adaptor (''add'', ''addAll'', ''clear'', ''insert'', ''remove'') apelează în mod automat ''notifyDataSetChanged''. Acest comportament poate fi suprascris prin intermediul metodei ''setNotifyOnChange(boolean)''.</note> | + | <note tip>Metodele pentru modificarea colecției de date prin intermediul obiectului de tip adaptor (''add'', ''addAll'', ''clear'', ''insert'', ''remove'') apelează în mod automat ''notifyDataSetChanged()''. Acest comportament poate fi suprascris prin intermediul metodei ''setNotifyOnChange(boolean)''.</note> |
| <note tip>Ordonarea elementelor din sursa de date poate fi realizată prin obiectul de tip adapter, pe baza unui criteriu de comparare, prin intermediul metodei ''sort(Comparator<? super T>)''.</note> | <note tip>Ordonarea elementelor din sursa de date poate fi realizată prin obiectul de tip adapter, pe baza unui criteriu de comparare, prin intermediul metodei ''sort(Comparator<? super T>)''.</note> | ||
| Line 527: | Line 527: | ||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
| - | xmlns:tools="http://schemas.android.com/tools" | + | xmlns:tools="http://schemas.android.com/tools" |
| - | android:layout_width="match_parent" | + | android:layout_width="match_parent" |
| - | android:layout_height="match_parent" > | + | android:layout_height="match_parent" > |
| - | <ImageView | + | <ImageView |
| - | android:id="@+id/imageview" | + | android:id="@+id/imageview" |
| - | android:layout_width="wrap_content" | + | android:layout_width="wrap_content" |
| - | android:layout_height="wrap_content" | + | android:layout_height="wrap_content" |
| - | android:padding="2dp" | + | android:padding="2dp" |
| - | android:contentDescription="@string/content_description" /> | + | android:contentDescription="@string/content_description" /> |
| - | <TextView | + | <TextView |
| - | android:id="@+id/textview" | + | android:id="@+id/textview" |
| - | android:layout_width="wrap_content" | + | android:layout_width="wrap_content" |
| - | android:layout_height="wrap_content" /> | + | android:layout_height="wrap_content" /> |
| </LinearLayout> | </LinearLayout> | ||
| </file> | </file> | ||
| Line 547: | Line 547: | ||
| <code java> | <code java> | ||
| class PointArrayAdapter extends ArrayAdapter<Point> { | class PointArrayAdapter extends ArrayAdapter<Point> { | ||
| - | private Context context; | + | private Context context; |
| - | private int resource; | + | private int resource; |
| - | private ArrayList<Point> content; | + | private ArrayList<Point> content; |
| - | public PointArrayAdapter(Context context, int resource, ArrayList<Point> content) { | + | public PointArrayAdapter(Context context, int resource, ArrayList<Point> content) { |
| - | super(context, resource, content); | + | super(context, resource, content); |
| - | this.context = context; | + | this.context = context; |
| - | this.resource = resource; | + | this.resource = resource; |
| - | this.content = content; | + | this.content = content; |
| - | } | + | } |
| - | @Override | + | @Override |
| - | public View getView(int position, View convertView, ViewGroup parent) { | + | public View getView(int position, View convertView, ViewGroup parent) { |
| - | View view; | + | View view; |
| - | if (convertView == null) { | + | if (convertView == null) { |
| - | LayoutInflater layoutinflator = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); | + | LayoutInflater layoutinflator = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); |
| - | view = layoutinflator.inflate(resource, null); | + | view = layoutinflator.inflate(resource, null); |
| - | } | + | } else { |
| - | else | + | view = convertView; |
| - | view = convertView; | + | |
| - | ImageView imageview = (ImageView)view.findViewById(R.id.imageview); | + | |
| - | TextView textview = (TextView)view.findViewById(R.id.textview); | + | |
| - | Point point = content.get(position); | + | |
| - | if (point.getX() >= 0 && point.getY() >= 0) | + | |
| - | imageview.setImageResource(R.drawable.firstquadrant); | + | |
| - | else if (point.getX() < 0 && point.getY() >= 0) | + | |
| - | imageview.setImageResource(R.drawable.secondquadrant); | + | |
| - | else if (point.getX() < 0 && point.getY() < 0) | + | |
| - | imageview.setImageResource(R.drawable.thirdquadrant); | + | |
| - | else if (point.getX() >= 0 && point.getY() < 0) | + | |
| - | imageview.setImageResource(R.drawable.forthquadrant); | + | |
| - | textview.setText(point.toString()); | + | |
| - | return view; | + | |
| } | } | ||
| + | ImageView imageview = (ImageView)view.findViewById(R.id.imageview); | ||
| + | TextView textview = (TextView)view.findViewById(R.id.textview); | ||
| + | Point point = content.get(position); | ||
| + | if (point.getX() >= 0 && point.getY() >= 0) { | ||
| + | imageview.setImageResource(R.drawable.firstquadrant); | ||
| + | } else if (point.getX() < 0 && point.getY() >= 0) { | ||
| + | imageview.setImageResource(R.drawable.secondquadrant); | ||
| + | } else if (point.getX() < 0 && point.getY() < 0) { | ||
| + | imageview.setImageResource(R.drawable.thirdquadrant); | ||
| + | } else if (point.getX() >= 0 && point.getY() < 0) { | ||
| + | imageview.setImageResource(R.drawable.forthquadrant); | ||
| + | } | ||
| + | textview.setText(point.toString()); | ||
| + | return view; | ||
| + | } | ||
| } | } | ||
| </code> | </code> | ||
| Line 597: | Line 598: | ||
| </code> | </code> | ||
| - | {{ :laboratoare:sample_base_adapter.png?nolink&500 }} | + | {{ :laboratoare:laborator05:sample_base_addapter.png?nolink&400 }} |
| === SimpleCursorAdapter === | === SimpleCursorAdapter === | ||
| Line 639: | Line 640: | ||
| <file java CalendarActivity.java> | <file java CalendarActivity.java> | ||
| public class CalendarActivity extends Activity { | public class CalendarActivity extends Activity { | ||
| - | @Override | + | @Override |
| - | protected void onCreate(Bundle savedInstanceState) { | + | protected void onCreate(Bundle savedInstanceState) { |
| - | super.onCreate(savedInstanceState); | + | super.onCreate(savedInstanceState); |
| - | setContentView(R.layout.activity_main); | + | setContentView(R.layout.activity_main); |
| - | Cursor cursor = getContentResolver().query( | + | Cursor cursor = getContentResolver().query( |
| - | Calendars.CONTENT_URI, | + | Calendars.CONTENT_URI, |
| - | new String[]{Calendars._ID, Calendars.CALENDAR_DISPLAY_NAME, Calendars.CALENDAR_TIME_ZONE}, | + | new String[]{Calendars._ID, Calendars.CALENDAR_DISPLAY_NAME, Calendars.CALENDAR_TIME_ZONE}, |
| - | null, | + | null, |
| - | null, | + | null, |
| - | null); | + | null); |
| - | SimpleCursorAdapter adapter = new SimpleCursorAdapter( | + | SimpleCursorAdapter adapter = new SimpleCursorAdapter( |
| - | this, | + | this, |
| - | android.R.layout.two_line_list_item, | + | android.R.layout.two_line_list_item, |
| - | cursor, | + | cursor, |
| - | new String[]{Calendars.CALENDAR_DISPLAY_NAME, Calendars.CALENDAR_TIME_ZONE}, | + | new String[]{Calendars.CALENDAR_DISPLAY_NAME, Calendars.CALENDAR_TIME_ZONE}, |
| - | new int[] {android.R.id.text1, android.R.id.text2}, | + | new int[] {android.R.id.text1, android.R.id.text2}, |
| - | 0); | + | 0); |
| - | ListView listview = (ListView)findViewById(R.id.listview); | + | ListView listview = (ListView)findViewById(R.id.listview); |
| - | listview.setAdapter(adapter); | + | listview.setAdapter(adapter); |
| - | } | + | } |
| } | } | ||
| </file> | </file> | ||
| Line 682: | Line 683: | ||
| public class StaffMemberActivity extends Activity { | public class StaffMemberActivity extends Activity { | ||
| - | @Override | + | @Override |
| - | protected void onCreate(Bundle savedInstanceState) { | + | protected void onCreate(Bundle savedInstanceState) { |
| - | super.onCreate(savedInstanceState); | + | super.onCreate(savedInstanceState); |
| - | setContentView(R.layout.activity_staff_member); | + | setContentView(R.layout.activity_staff_member); |
| - | + | ||
| - | try { | + | try { |
| - | InputStream inputstream = getAssets().open("staffmember.xml"); | + | InputStream inputstream = getAssets().open("staffmember.xml"); |
| - | StaffXmlParser staffxmlparser = new StaffXmlParser(); | + | StaffXmlParser staffxmlparser = new StaffXmlParser(); |
| - | List<Map<String,?>> staffmembers = staffxmlparser.parse(inputstream); | + | List<Map<String,?>> staffmembers = staffxmlparser.parse(inputstream); |
| - | SimpleAdapter adapter = new SimpleAdapter( | + | SimpleAdapter adapter = new SimpleAdapter( |
| - | this, | + | this, |
| - | staffmembers, | + | staffmembers, |
| - | android.R.layout.simple_list_item_2, | + | android.R.layout.simple_list_item_2, |
| - | new String[] {"name", "position"}, | + | new String[] {"name", "position"}, |
| - | new int[] {android.R.id.text1, android.R.id.text2}); | + | new int[] {android.R.id.text1, android.R.id.text2}); |
| - | ListView listview = (ListView)findViewById(R.id.listview) | + | ListView listview = (ListView)findViewById(R.id.listview) |
| - | listview.setAdapter(adapter); | + | listview.setAdapter(adapter); |
| - | } catch (Exception exception) { | + | } catch (Exception exception) { |
| - | Log.println(Log.ERROR, "exception", exception.getMessage()); | + | Log.println(Log.ERROR, "exception", exception.getMessage()); |
| - | } | + | |
| } | } | ||
| + | } | ||
| } | } | ||
| </file> | </file> | ||
| Line 719: | Line 720: | ||
| </code> | </code> | ||
| - | * metoda ''getCount'' furnizează numărul de elemente din cadrul listei; | + | * metoda ''getCount()'' furnizează numărul de elemente din cadrul listei; |
| - | * metoda ''getItem'' întoarce elementul care se află pe o anumită poziție în cadrul listei; | + | * metoda ''getItem()'' întoarce elementul care se află pe o anumită poziție în cadrul listei; |
| - | * metoda ''getItemId'' returnează identificatorul elementului de pe o anumită poziție în cadrul listei; | + | * metoda ''getItemId()'' returnează identificatorul elementului de pe o anumită poziție în cadrul listei; |
| - | * metoda ''getView'' construiește un control grafic corespunzător elementului de pe o anumită poziție în cadrul listei; acesta poate fi o instanță nouă, existând totodată posibilitatea de a se reutiliza parametrul ''convertView'' (care reprezintă o componentă a listei creată anterior, ce nu mai este vizibilă, putând fi astfel reciclată); obiectul ''parent'' indică elementul de tip container în care este afișat conținutul sursei de date. | + | * metoda ''getView()'' construiește un control grafic corespunzător elementului de pe o anumită poziție în cadrul listei; acesta poate fi o instanță nouă, existând totodată posibilitatea de a se reutiliza parametrul ''convertView'' (care reprezintă o componentă a listei creată anterior, ce nu mai este vizibilă, putând fi astfel reciclată); obiectul ''parent'' indică elementul de tip container în care este afișat conținutul sursei de date. |
| <note important>Clasa care implementează tipul de adaptor definit de utilizator trebuie să conțină (intern) și modelul de date, operând asupra acestuia.</note> | <note important>Clasa care implementează tipul de adaptor definit de utilizator trebuie să conțină (intern) și modelul de date, operând asupra acestuia.</note> | ||
| Line 733: | Line 734: | ||
| </code> | </code> | ||
| - | * metoda ''getViewTypeCount'' va întoarce numărul tipurilor de layout-uri care vor fi afișate în cadrul listei; | + | * metoda ''getViewTypeCount()'' va întoarce numărul tipurilor de layout-uri care vor fi afișate în cadrul listei; |
| - | * metoda ''getItemViewType'' returnează - pentru elementul aflat pe o anumită poziție - mecanismul de dispunere care va fi utilizat. | + | * metoda ''getItemViewType()'' returnează - pentru elementul aflat pe o anumită poziție - mecanismul de dispunere care va fi utilizat. |
| - | Spre exemplu, pentru gestiunea unei liste formată dintr-un ''ImageView'' și două ''TextView'', dispuse diferit în funcție de rândul pe care se găsesc, vor trebui definite două layout-uri (în ''/res/layout'') - denumite ''odd_layout.xml'' și ''even_layout.xml'' ce vor fi încărcate de metoda ''getView'' în funcție de poziția respectivă: | + | Spre exemplu, pentru gestiunea unei liste formată dintr-un ''ImageView'' și două ''TextView'', dispuse diferit în funcție de rândul pe care se găsesc, vor trebui definite două layout-uri (în ''/res/layout'') - denumite ''odd_layout.xml'' și ''even_layout.xml'' ce vor fi încărcate de metoda ''getView()'' în funcție de poziția respectivă: |
| {{ :laboratoare:laborator05:listview_definit_de_utilizator.png?nolink }} | {{ :laboratoare:laborator05:listview_definit_de_utilizator.png?nolink }} | ||
| Line 743: | Line 744: | ||
| public class CustomAdapter extends BaseAdapter { | public class CustomAdapter extends BaseAdapter { | ||
| - | Activity context; | + | Activity context; |
| - | List<CustomObject> data; | + | List<CustomObject> data; |
| - | // ... | + | // ... |
| - | @Override | + | @Override |
| - | public View getView(int position, View convertView, ViewGroup parent) { | + | public View getView(int position, View convertView, ViewGroup parent) { |
| - | View customView; | + | View customView; |
| - | CustomObject customObject = data.get(position); | + | CustomObject customObject = data.get(position); |
| - | LayoutInflater layoutInflater = (LayoutInflater)context.getLayoutInflater(); | + | LayoutInflater layoutInflater = (LayoutInflater)context.getLayoutInflater(); |
| - | if (position % 2 == 0) | + | if (position % 2 == 0) { |
| - | customView = layoutInflater.inflate(R.layout.odd_layout, parent, false); | + | customView = layoutInflater.inflate(R.layout.odd_layout, parent, false); |
| - | else | + | } else { |
| - | customView = layoutInflater.inflate(R.layout.even_layout, parent, false); | + | customView = layoutInflater.inflate(R.layout.even_layout, parent, false); |
| - | ImageView imageView = (ImageView)customView.findViewById(R.id.imageView); | + | |
| - | imageView.setImageResource(customObject.getImageId()); | + | |
| - | TextView textView1 = (TextView)customView.findViewById(R.id.textView1); | + | |
| - | textView1.setText(customObject.getText1()); | + | |
| - | TextView textView2 = (TextView)customView.findViewById(R.id.textView2); | + | |
| - | textView2.setText(customObject.getText2()); | + | |
| - | return customView; | + | |
| } | } | ||
| + | ImageView imageView = (ImageView)customView.findViewById(R.id.imageView); | ||
| + | imageView.setImageResource(customObject.getImageId()); | ||
| + | TextView textView1 = (TextView)customView.findViewById(R.id.textView1); | ||
| + | textView1.setText(customObject.getText1()); | ||
| + | TextView textView2 = (TextView)customView.findViewById(R.id.textView2); | ||
| + | textView2.setText(customObject.getText2()); | ||
| + | return customView; | ||
| + | } | ||
| } | } | ||
| </code> Clasa adaptor definită de utilizator va trebui să rețină referințe către context (activitatea în cadrul căreia este afișată lista) și către sursa de date. | </code> Clasa adaptor definită de utilizator va trebui să rețină referințe către context (activitatea în cadrul căreia este afișată lista) și către sursa de date. | ||
| - | Metoda ''getView'' construiește un element de pe o anumită poziție din cadrul listei pe care îl va întoarce apoi ca rezultat. | + | Metoda ''getView()'' construiește un element de pe o anumită poziție din cadrul listei pe care îl va întoarce apoi ca rezultat. |
| Inițial, trebuie să se obțină conținutul intrării din listă ce trebuie afișată (considerându-se o corespondență 1:1 între conținutul sursei de date și elementele listei) și să se instanțieze obiectul responsabil cu expandarea layout-ului. Ulterior se obține obiectul de tip ''View'' pe baza mecanismului de dispunere (corespunzător poziției curente) specificat în fișierul XML. Acesta va furniza referințe către controalele din cadrul său (prin intermediul identificatorilor unici) pentru care se va putea specifica conținutul, preluat din obiectul curent al sursei de date. | Inițial, trebuie să se obțină conținutul intrării din listă ce trebuie afișată (considerându-se o corespondență 1:1 între conținutul sursei de date și elementele listei) și să se instanțieze obiectul responsabil cu expandarea layout-ului. Ulterior se obține obiectul de tip ''View'' pe baza mecanismului de dispunere (corespunzător poziției curente) specificat în fișierul XML. Acesta va furniza referințe către controalele din cadrul său (prin intermediul identificatorilor unici) pentru care se va putea specifica conținutul, preluat din obiectul curent al sursei de date. | ||
| == Tehnici pentru optimizarea performanțelor == | == Tehnici pentru optimizarea performanțelor == | ||
| + | |||
| Implementarea unor tehnici pentru optimizarea performanțelor este foarte importantă atunci când se dezvoltă aplicații pentru dispozitive mobile. Având în vedere resursele limitate (în special în privința memoriei și a capacității de procesare) de care dispun acestea, un program care nu le gestionează în mod eficient poate determina o depreciere a timpului de răspuns. | Implementarea unor tehnici pentru optimizarea performanțelor este foarte importantă atunci când se dezvoltă aplicații pentru dispozitive mobile. Având în vedere resursele limitate (în special în privința memoriei și a capacității de procesare) de care dispun acestea, un program care nu le gestionează în mod eficient poate determina o depreciere a timpului de răspuns. | ||
| - | Fiecare element din cadrul unei liste este un ''View'' obținut prin expandarea layout-ului, atât construirea obiectului pentru gestiunea modurilor de dispunere (metoda ''getLayoutInflater'') cât și operația de instanțiere a unei intrări din listă pe baza specificației XML (metoda ''inflate'') fiind operații extrem de costisitoare. De asemenea, obținerea unei referințe către un control din cadrul interfeței grafice pe baza identificatorului său (metoda ''findViewById'') poate avea afecta performanțele aplicației. | + | Fiecare element din cadrul unei liste este un ''View'' obținut prin expandarea layout-ului, atât construirea obiectului pentru gestiunea modurilor de dispunere (metoda ''getLayoutInflater()'') cât și operația de instanțiere a unei intrări din listă pe baza specificației XML (metoda ''inflate()'') fiind operații extrem de costisitoare. De asemenea, obținerea unei referințe către un control din cadrul interfeței grafice pe baza identificatorului său (metoda ''findViewById()'') poate avea afecta performanțele aplicației. |
| Printre cele mai utilizate tehnici pentru optimizarea performanțelor se numără: | Printre cele mai utilizate tehnici pentru optimizarea performanțelor se numără: | ||
| Line 781: | Line 784: | ||
| * **instanțierea obiectului responsabil cu expandarea mecanismului de dispunere a unui element din cadrul listei pe constructorul clasei adaptor** <code java> | * **instanțierea obiectului responsabil cu expandarea mecanismului de dispunere a unui element din cadrul listei pe constructorul clasei adaptor** <code java> | ||
| public CustomAdapter(Activity context, List<CustomObject> data) { | public CustomAdapter(Activity context, List<CustomObject> data) { | ||
| - | this.data = data; | + | this.data = data; |
| - | layoutInflater = (LayoutInflater)context.getLayoutInflater(); | + | layoutInflater = (LayoutInflater)context.getLayoutInflater(); |
| } | } | ||
| </code> În acest fel, se evită apelul acestei metode - costisitoare din punctul de vedere al utilizării resurselor - de fiecare dată când trebuie creat un element al listei. | </code> În acest fel, se evită apelul acestei metode - costisitoare din punctul de vedere al utilizării resurselor - de fiecare dată când trebuie creat un element al listei. | ||
| - | * **reutilizarea elementelor din cadrul listei care nu mai sunt vizibile** \\ De regulă, o listă conține mai multe elemente decât pot fi reprezentate pe suprafața de afișare a dispozitivului mobil, parcurgerea lor implicând folosirea unui mecanism de derulare. Obiectele corespunzătoare unor intrări care nu sunt vizibile la un moment dat pot fi reutilizate, ele fiind transmise în metoda ''getView'' prin intermediul parametrului ''convertView'', prevenindu-se astfel operația de expandare a layout-ului.\\ <code java>@Override | + | * **reutilizarea elementelor din cadrul listei care nu mai sunt vizibile** \\ De regulă, o listă conține mai multe elemente decât pot fi reprezentate pe suprafața de afișare a dispozitivului mobil, parcurgerea lor implicând folosirea unui mecanism de derulare. Obiectele corespunzătoare unor intrări care nu sunt vizibile la un moment dat pot fi reutilizate, ele fiind transmise în metoda ''getView()'' prin intermediul parametrului ''convertView'', prevenindu-se astfel operația de expandare a layout-ului.\\ <code java> |
| + | @Override | ||
| public View getView(int position, View convertView, ViewGroup parent) { | public View getView(int position, View convertView, ViewGroup parent) { | ||
| - | View customView; | + | View customView; |
| - | CustomObject customObject = data.get(position); | + | CustomObject customObject = data.get(position); |
| - | if (convertView == null) { | + | if (convertView == null) { |
| - | if (position % 2 == 0) | + | if (position % 2 == 0) { |
| - | customView = layoutInflater.inflate(R.layout.odd_layout, parent, false); | + | customView = layoutInflater.inflate(R.layout.odd_layout, parent, false); |
| - | else | + | } else { |
| - | customView = layoutInflater.inflate(R.layout.even_layout, parent, false); | + | customView = layoutInflater.inflate(R.layout.even_layout, parent, false); |
| } | } | ||
| - | else | + | } |
| - | customView = convertView; | + | else { |
| - | // ... | + | customView = convertView; |
| - | return customView; | + | } |
| + | // ... | ||
| + | return customView; | ||
| } | } | ||
| - | </code> Prin această metodă se evită apelarea metodei ''inflate'' de fiecare dată când trebuie să se afișeze un element al listei. | + | </code> Prin această metodă se evită apelarea metodei ''inflate()'' de fiecare dată când trebuie să se afișeze un element al listei. |
| - | <note important>Nu întotdeauna este posibilă reutilizarea obiectelor ce reprezintă elemente ale listei, situație în care parametrul ''convertView'' are valoarea ''null''. De aceea, în metoda ''getView'' trebuie verificată întotdeauna valoarea acestui parametru.</note> | + | <note important>Nu întotdeauna este posibilă reutilizarea obiectelor ce reprezintă elemente ale listei, situație în care parametrul ''convertView'' are valoarea ''null''. De aceea, în metoda ''getView()'' trebuie verificată întotdeauna valoarea acestui parametru.</note> |
| - | <note warning> În cazul în care există mai multe posibilități de dispunere în cadrul listei, există riscul ca tipul de element care va fi reutilizat să nu fie cel necesar. Pentru a se asigura evitarea unei astfel de situații, este necesară suprascrierea metodelor ''getViewTypeCount'', respectiv ''getItemViewType''. | + | <note warning> În cazul în care există mai multe posibilități de dispunere în cadrul listei, există riscul ca tipul de element care va fi reutilizat să nu fie cel necesar. Pentru a se asigura evitarea unei astfel de situații, este necesară suprascrierea metodelor ''getViewTypeCount()'', respectiv ''getItemViewType()''. |
| <code java> | <code java> | ||
| public final static int LIST_VIEW_TYPES = 2; | public final static int LIST_VIEW_TYPES = 2; | ||
| Line 809: | Line 815: | ||
| public int getViewTypeCount() { | public int getViewTypeCount() { | ||
| - | return LIST_VIEW_TYPES; | + | return LIST_VIEW_TYPES; |
| } | } | ||
| public Object getItemViewType(int position) { | public Object getItemViewType(int position) { | ||
| - | if (position % 2 == 0) | + | if (position % 2 == 0) |
| - | return LIST_VIEW_TYPE_ODD; | + | return LIST_VIEW_TYPE_ODD; |
| - | return LIST_VIEW_TYPE_EVEN; | + | return LIST_VIEW_TYPE_EVEN; |
| } | } | ||
| </code> | </code> | ||
| </note> | </note> | ||
| - | * **reținerea unei referințe către structura layout-ului prin intermediul unor etichete**\\ În acest scop se utilizează un șablon denumit ''ViewHolder'' prin intermediul căruia pot fi accesate controalele grafice din cadrul unui element al listei, fără a fi necesară utilizarea identificatorului din cadrul documentului XML.\\ \\ ''ViewHolder'' este o clasă internă din cadrul adaptorului, definind exact structura pe care o are layout-ul unei intrări din cadrul listei. În momentul în care un obiect corespunzător unui element al listei este creat, în atributele clasei ''ViewHolder'' se rețin referințe către controalele grafice, acestea fiind atașate, ca etichetă, prin intermediul metodei ''setTag''. Ulterior, ele vor fi preluate (prin metoda ''getTag''), utilizându-se referințele către elementele componente în loc să se apeleze metoda ''findViewById'' de fiecare data, rezultatul fiind o apreciere a performanțelor cu circa 15%.\\ <code java> | + | * **reținerea unei referințe către structura layout-ului prin intermediul unor etichete**\\ În acest scop se utilizează un șablon denumit ''ViewHolder'' prin intermediul căruia pot fi accesate controalele grafice din cadrul unui element al listei, fără a fi necesară utilizarea identificatorului din cadrul documentului XML.\\ \\ ''ViewHolder'' este o clasă internă din cadrul adaptorului, definind exact structura pe care o are layout-ul unei intrări din cadrul listei. În momentul în care un obiect corespunzător unui element al listei este creat, în atributele clasei ''ViewHolder'' se rețin referințe către controalele grafice, acestea fiind atașate, ca etichetă, prin intermediul metodei ''setTag()''. Ulterior, ele vor fi preluate (prin metoda ''getTag()''), utilizându-se referințele către elementele componente în loc să se apeleze metoda ''findViewById()'' de fiecare data, rezultatul fiind o apreciere a performanțelor cu circa 15%.\\ <code java> |
| public class CustomAdapter extends BaseAdapter { | public class CustomAdapter extends BaseAdapter { | ||
| - | public static class ViewHolder { | + | public static class ViewHolder { |
| - | ImageView imageView; | + | ImageView imageView; |
| - | TextView textView1, textView2; | + | TextView textView1, textView2; |
| - | }; | + | }; |
| - | // ... | + | // ... |
| - | @Override | + | @Override |
| - | public View getView(int position, View convertView, ViewGroup parent) { | + | public View getView(int position, View convertView, ViewGroup parent) { |
| - | View customView; | + | View customView; |
| - | ViewHolder viewHolder; | + | ViewHolder viewHolder; |
| - | CustomObject customObject = (CustomObject)data.get(position); | + | CustomObject customObject = (CustomObject)data.get(position); |
| - | if (convertView == null) { | + | if (convertView == null) { |
| - | if (position % 2 == 0) | + | if (position % 2 == 0) { |
| - | customView = layoutInflater.inflate(R.layout.odd_layout, parent, false); | + | customView = layoutInflater.inflate(R.layout.odd_layout, parent, false); |
| - | else | + | } else { |
| - | customView = layoutInflater.inflate(R.layout.even_layout, parent, false); | + | customView = layoutInflater.inflate(R.layout.even_layout, parent, false); |
| - | viewHolder = new ViewHolder(); | + | } |
| - | viewHolder.imageView = (ImageView)customView.findViewById(R.id.imageView); | + | viewHolder = new ViewHolder(); |
| - | viewHolder.textView1 = (TextView)customView.findViewById(R.id.textView1); | + | viewHolder.imageView = (ImageView)customView.findViewById(R.id.imageView); |
| - | viewHolder.textView2 = (TextView)customView.findViewById(R.id.textView2); | + | viewHolder.textView1 = (TextView)customView.findViewById(R.id.textView1); |
| - | customView.setTag(viewHolder); | + | viewHolder.textView2 = (TextView)customView.findViewById(R.id.textView2); |
| - | } | + | customView.setTag(viewHolder); |
| - | else | + | } else { |
| - | customView = convertView; | + | customView = convertView; |
| - | viewHolder = (ViewHolder)customView.getTag(); | + | |
| - | viewHolder.imageView.setImageResource(customObject.getImageeId()); | + | |
| - | viewHolder.textView1.setText(customObject.getText1()); | + | |
| - | viewHolder.textView2.setText(customObject.getText2()); | + | |
| - | + | ||
| - | return customView; | + | |
| } | } | ||
| + | viewHolder = (ViewHolder)customView.getTag(); | ||
| + | viewHolder.imageView.setImageResource(customObject.getImageeId()); | ||
| + | viewHolder.textView1.setText(customObject.getText1()); | ||
| + | viewHolder.textView2.setText(customObject.getText2()); | ||
| + | | ||
| + | return customView; | ||
| + | } | ||
| } | } | ||
| </code> | </code> | ||
| Line 863: | Line 870: | ||
| <code xml> | <code xml> | ||
| <ListView | <ListView | ||
| - | android:id="@android:id/list" | + | android:id="@android:id/list" |
| - | android:layout_width="match_parent" | + | android:layout_width="match_parent" |
| - | android:layout_height="wrap_content" /> | + | android:layout_height="wrap_content" /> |
| </code> | </code> | ||
| </note> | </note> | ||
| Line 890: | Line 897: | ||
| * ''v'' - elementul din cadrul listei care a fost apăsat | * ''v'' - elementul din cadrul listei care a fost apăsat | ||
| * ''position'' - poziția elementului care a fost apăsat în cadrul listei | * ''position'' - poziția elementului care a fost apăsat în cadrul listei | ||
| - | * ''id'' - identificatorul elementului care a fost apăsat în cadrul listei (întors de metoda ''getItemId'' a clasei adaptor) | + | * ''id'' - identificatorul elementului care a fost apăsat în cadrul listei (întors de metoda ''getItemId()'' a clasei adaptor) |
| Clasa ''ListActivity'' nu definește însă și o metodă pentru tratarea apăsărilor de lungă durată (//eng.// long-click), în acest sens fiind necesară implementarea unei clase ascultător ce implementează interfața ''AdapterView.OnItemLongClickListener'', asociată obiectului de tip ''ListView'' din cadrul ferestrei. | Clasa ''ListActivity'' nu definește însă și o metodă pentru tratarea apăsărilor de lungă durată (//eng.// long-click), în acest sens fiind necesară implementarea unei clase ascultător ce implementează interfața ''AdapterView.OnItemLongClickListener'', asociată obiectului de tip ''ListView'' din cadrul ferestrei. | ||
| Line 904: | Line 911: | ||
| Metodele pe care le pune la dispoziție ''ListFragment'' sunt similare cu cele oferite de ''ListActivity''. | Metodele pe care le pune la dispoziție ''ListFragment'' sunt similare cu cele oferite de ''ListActivity''. | ||
| - | <note important>În cazul în care se dorește gestiunea unei aplicații cu mai multe fragmente utilizând liste, acestea vor fi incluse într-o fereastră ce extinde ''FragmentActivity'' și nu ''ListActivity'', în caz contrar evenimentele de tip apăsare a unui element fiind consumate de clasa părinte.\\ Se recomandă folosirea claselor definite în pachetul ''android.support.v4.app''. | + | <note important>În cazul în care se dorește gestiunea unei aplicații cu mai multe fragmente utilizând liste, acestea vor fi incluse într-o fereastră ce extinde ''FragmentActivity'' și nu ''ListActivity'', în caz contrar evenimentele de tip apăsare a unui element fiind consumate de clasa părinte. |
| </note> | </note> | ||
| - | Pentru utilizarea de layout-uri definite de utilizatori, lista implicită trebuie referită prin ''android:id/list'', mecanismul de dispunere fiind încărcat pe metoda ''onCreateView''. | + | Pentru utilizarea de layout-uri definite de utilizatori, lista implicită trebuie referită prin ''android:id/list'', mecanismul de dispunere fiind încărcat pe metoda ''onCreateView()''. |
| <code java> | <code java> | ||
| @Override | @Override | ||
| public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state) { | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state) { | ||
| - | View view = inflater.inflate(R.layout.fragment_custom, container, false); | + | View view = inflater.inflate(R.layout.fragment_custom, container, false); |
| - | return view; | + | return view; |
| } | } | ||
| </code> | </code> | ||
| Line 921: | Line 928: | ||
| @Override | @Override | ||
| public void onActivityCreated(Bundle state) { | public void onActivityCreated(Bundle state) { | ||
| - | super.onActivityCreated(state); | + | super.onActivityCreated(state); |
| - | CustomAdapter customAdapter = new CustomAdapter(getActivity(), data); | + | CustomAdapter customAdapter = new CustomAdapter(getActivity(), data); |
| - | setListAdapter(customAdapter); | + | setListAdapter(customAdapter); |
| } | } | ||
| </code> | </code> | ||
| Line 932: | Line 939: | ||
| - **static**, dacă fragmentul respectiv nu va fi înlocuit în cadrul interfeței grafice (sau în situația în care este înlocuit, el este păstrat pe stivă prin apelul metodei ''addToBackStack()'', pentru a se putea reveni la el)\\ <code xml> | - **static**, dacă fragmentul respectiv nu va fi înlocuit în cadrul interfeței grafice (sau în situația în care este înlocuit, el este păstrat pe stivă prin apelul metodei ''addToBackStack()'', pentru a se putea reveni la el)\\ <code xml> | ||
| <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
| - | xmlns:tools="http://schemas.android.com/tools" | + | xmlns:tools="http://schemas.android.com/tools" |
| + | android:layout_width="match_parent" | ||
| + | android:layout_height="match_parent" | ||
| + | tools:context=".MainActivity" > | ||
| + | |||
| + | <fragment | ||
| + | android:id="@+id/fragment1" | ||
| + | android:name="ro.pub.cs.systems.pdsd.lab05.Fragment1" | ||
| android:layout_width="match_parent" | android:layout_width="match_parent" | ||
| - | android:layout_height="match_parent" | + | android:layout_height="wrap_content" /> |
| - | tools:context=".MainActivity" > | + | |
| - | + | ||
| - | <fragment | + | |
| - | android:id="@+id/fragment1" | + | |
| - | android:name="ro.pub.cs.pdsd.laborator04.view.Fragment1" | + | |
| - | android:layout_width="match_parent" | + | |
| - | android:layout_height="wrap_content" /> | + | |
| </RelativeLayout> | </RelativeLayout> | ||
| Line 954: | Line 961: | ||
| </code> De remarcat faptul că pentru fragment au fost specificate următoarele proprietăți: | </code> De remarcat faptul că pentru fragment au fost specificate următoarele proprietăți: | ||
| * ''android:id'' prin intermediul căruia fragmentul poate fi identificat în mod unic (alternativ se poate specifica ''android:tag'') | * ''android:id'' prin intermediul căruia fragmentul poate fi identificat în mod unic (alternativ se poate specifica ''android:tag'') | ||
| - | * ''android:name'' reprezentând clasa corespunzătoare fragmentului, care va fi instanțiată în momentul în care este expandat layoutul corespunzător activității (în locul elementului ''<fragment>'' va fi plasat rezultatul metodei ''onCreateView'')\\ | + | * ''android:name'' reprezentând clasa corespunzătoare fragmentului, care va fi instanțiată în momentul în care este expandat layoutul corespunzător activității (în locul elementului ''<fragment>'' va fi plasat rezultatul metodei ''onCreateView()'')\\ |
| - **dinamic**, în situația în care conținutul fragmentului va fi diferit, în funcție de anumite operații realizate de utilizator\\ <code xml> | - **dinamic**, în situația în care conținutul fragmentului va fi diferit, în funcție de anumite operații realizate de utilizator\\ <code xml> | ||
| <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
| - | xmlns:tools="http://schemas.android.com/tools" | + | xmlns:tools="http://schemas.android.com/tools" |
| - | android:layout_width="match_parent" | + | android:layout_width="match_parent" |
| - | android:layout_height="match_parent" | + | android:layout_height="match_parent" |
| - | tools:context=".CartoonActivity" > | + | tools:context=".CartoonActivity" > |
| | | ||
| - | <FrameLayout | + | <FrameLayout |
| - | android:id="@+id/fragment1" | + | android:id="@+id/fragment1" |
| - | android:layout_width="0dp" | + | android:layout_width="0dp" |
| - | android:layout_height="match_parent" | + | android:layout_height="match_parent" |
| - | android:layout_weight="1" /> | + | android:layout_weight="1" /> |
| </RelativeLayout> | </RelativeLayout> | ||
| Line 986: | Line 993: | ||
| * 0 sau mai multe submeniuri (reprezentate de clasa ''android.view.SubMenu'') | * 0 sau mai multe submeniuri (reprezentate de clasa ''android.view.SubMenu'') | ||
| * 0 sau mai multe intrări propriu-zise (reprezentate de clasa ''android.view.MenuItem''), caracterizate prin următoarele atribute: | * 0 sau mai multe intrări propriu-zise (reprezentate de clasa ''android.view.MenuItem''), caracterizate prin următoarele atribute: | ||
| - | * **denumire** reprezintă valoarea care este afișată în cadrul interfeței grafice | + | * **denumire** reprezintă valoarea care este afișată în cadrul interfeței grafice; |
| - | * **identificator** generat de obicei în mod automat pentru meniurile declarate prin intermediul fișierelor XML | + | * **identificator** generat de obicei în mod automat pentru meniurile declarate prin intermediul fișierelor XML; |
| - | * **identificator al grupului de meniuri** prin intermediul căruia mai multe opțiuni din cadrul meniului pot fi grupate împreună | + | * **identificator al grupului de meniuri** prin intermediul căruia mai multe opțiuni din cadrul meniului pot fi grupate împreună; |
| * **număr de ordine** specifică importanța intrării, determinând o sortare a acestora, fiind folosit pentru a se indica ordinea de afișare a meniurilor sau pentru a preciza faptul că întregul grup aparține unei categorii (identificatorul grupului de meniuri fiind același cu numărul de ordine); unele intervale sunt rezervate pentru anumite categorii de meniuri | * **număr de ordine** specifică importanța intrării, determinând o sortare a acestora, fiind folosit pentru a se indica ordinea de afișare a meniurilor sau pentru a preciza faptul că întregul grup aparține unei categorii (identificatorul grupului de meniuri fiind același cu numărul de ordine); unele intervale sunt rezervate pentru anumite categorii de meniuri | ||
| Line 1008: | Line 1015: | ||
| @Override | @Override | ||
| public boolean onCreateOptionsMenu(Menu menu) { | public boolean onCreateOptionsMenu(Menu menu) { | ||
| - | // populate menu, via XML resource file or programatically | + | // populate menu, via XML resource file or programatically |
| - | return true; | + | return true; |
| } | } | ||
| </code> | </code> | ||
| Line 1015: | Line 1022: | ||
| Pentru sistemele Android anterioare versiunii 2.3.x, aceasta este apelată în mod automat atunci când utilizatorul accesează meniul, iar pentru sistemele Android anterioare versiunii 3.0 în momentul instanțierii activității, de vreme ce opțiunile meniului trebuie să fie accesibile și prin intermediul barei de acțiuni. | Pentru sistemele Android anterioare versiunii 2.3.x, aceasta este apelată în mod automat atunci când utilizatorul accesează meniul, iar pentru sistemele Android anterioare versiunii 3.0 în momentul instanțierii activității, de vreme ce opțiunile meniului trebuie să fie accesibile și prin intermediul barei de acțiuni. | ||
| - | <note important>Este foarte important ca rezultatul metodei ''onCreateOptionsMenu'' să fie ''true'', pentru a face meniul vizibil. În situația în care metoda întoarce ''false'', meniul va fi invizibil. </note> | + | <note important>Este foarte important ca rezultatul metodei ''onCreateOptionsMenu()'' să fie ''true'', pentru a face meniul vizibil. În situația în care metoda întoarce ''false'', meniul va fi invizibil. </note> |
| Mai multe informații cu privire la meniuri pot fi consultate [[http://developer.android.com/guide/topics/ui/menus.html|aici]]. | Mai multe informații cu privire la meniuri pot fi consultate [[http://developer.android.com/guide/topics/ui/menus.html|aici]]. | ||
| Line 1024: | Line 1031: | ||
| **1.** **prin intermediul unui fișier de resurse XML** plasat în ''res/menu'' - variantă preferată datorită faptului că: | **1.** **prin intermediul unui fișier de resurse XML** plasat în ''res/menu'' - variantă preferată datorită faptului că: | ||
| - | * meniul poate fi identificat prin intermediul unei denumiri (generată în mod automat în clasa ''R.menu'') | + | * meniul poate fi identificat prin intermediul unei denumiri (generată în mod automat în clasa ''R.menu''); |
| - | * intrările propriu-zise din cadrul meniului vor fi ordonate în mod automat, generarea identificatorilor corespunzătoare acestora realizându-se de asemenea automat | + | * intrările propriu-zise din cadrul meniului vor fi ordonate în mod automat, generarea identificatorilor corespunzători acestora realizându-se de asemenea automat; |
| - | * textele conținute vor fi localizate automat (prin referințele la fișierele ce conțin șiruri de caractere) | + | * textele conținute vor fi localizate automat (prin referințele la fișierele ce conțin șiruri de caractere); |
| - | * structura poate fi vizualizată mai clar, separându-se partea de prezentare (conținutului meniului) de logica aplicației (mecanismul de răspuns la acțiunile utilizatorului vis-a-vis de intrările ale meniului) | + | * structura poate fi vizualizată mai clar, separându-se partea de prezentare (conținutului meniului) de logica aplicației (mecanismul de răspuns la acțiunile utilizatorului vis-a-vis de intrările ale meniului); |
| - | * permite definirea de configurații diferite pentru diverse platforme (dimensiuni ale suprafeței de afișare) | + | * permite definirea de configurații diferite pentru diverse platforme (dimensiuni ale suprafeței de afișare). |
| <file xml /res/menu/main.xml> | <file xml /res/menu/main.xml> | ||
| <menu xmlns:android="http://schemas.android.com/apk/res/android" > | <menu xmlns:android="http://schemas.android.com/apk/res/android" > | ||
| - | <item | + | <item |
| - | android:id="@+id/operations" | + | android:id="@+id/operations" |
| - | android:title="@string/operations" > | + | android:title="@string/operations" > |
| - | <menu> | + | <menu> |
| - | <item | + | <item |
| - | android:id="@+id/create" | + | android:id="@+id/create" |
| - | android:icon="@drawable/create" | + | android:icon="@drawable/create" |
| - | android:orderInCategory="100" | + | |
| - | android:showAsAction="ifRoom" | + | |
| - | android:title="@string/create" /> | + | |
| - | <!-- add other submenu entries --> | + | |
| - | </menu> | + | |
| - | </item> | + | |
| - | <group | + | |
| - | android:id="@+id/generic_actions" | + | |
| - | android:visible="true" | + | |
| - | android:enabled="true" | + | |
| - | android:checkableBehavior="none" > | + | |
| - | <item | + | |
| - | android:id="@+id/settings" | + | |
| - | android:icon="@drawable/settings" | + | |
| - | android:orderInCategory="100" | + | |
| - | android:showAsAction="ifRoom" | + | |
| - | android:title="@string/settings" /> | + | |
| - | <!-- add other menu entries --> | + | |
| - | </group> | + | |
| - | <item | + | |
| - | android:id="@+id/help" | + | |
| - | android:icon="@drawable/help" | + | |
| android:orderInCategory="100" | android:orderInCategory="100" | ||
| - | android:showAsAction="ifRoom" | + | android:showAsAction="ifRoom" |
| - | android:title="@string/help" /> | + | android:title="@string/create" /> |
| - | <!-- add other menu entries --> | + | <!-- add other submenu entries --> |
| + | </menu> | ||
| + | </item> | ||
| + | <group | ||
| + | android:id="@+id/generic_actions" | ||
| + | android:visible="true" | ||
| + | android:enabled="true" | ||
| + | android:checkableBehavior="none" > | ||
| + | <item | ||
| + | android:id="@+id/settings" | ||
| + | android:icon="@drawable/settings" | ||
| + | android:orderInCategory="100" | ||
| + | android:showAsAction="ifRoom" | ||
| + | android:title="@string/settings" /> | ||
| + | <!-- add other menu entries --> | ||
| + | </group> | ||
| + | <item | ||
| + | android:id="@+id/help" | ||
| + | android:icon="@drawable/help" | ||
| + | android:orderInCategory="100" | ||
| + | android:showAsAction="ifRoom" | ||
| + | android:title="@string/help" /> | ||
| + | <!-- add other menu entries --> | ||
| </menu> | </menu> | ||
| </file> | </file> | ||
| Line 1070: | Line 1077: | ||
| **a.** ''<item>'' care creează | **a.** ''<item>'' care creează | ||
| - | * un submeniu (de tip ''android.view.Submenu'') în cazul în care are imbricat un alt element de tip ''<menu>'' | + | * un submeniu (de tip ''android.view.Submenu'') în cazul în care are imbricat un alt element de tip ''<menu>''; |
| - | * o intrare propriu-zisă a meniului (de tip ''android.view.MenuItem''), dacă nu conține alte elemente | + | * o intrare propriu-zisă a meniului (de tip ''android.view.MenuItem''), dacă nu conține alte elemente; |
| Atributele elementului ''<item>'' sunt: | Atributele elementului ''<item>'' sunt: | ||
| * ''android:id'' - un identificator unic pentru resursă care va fi utilizat ca referință pentru elementul respectiv | * ''android:id'' - un identificator unic pentru resursă care va fi utilizat ca referință pentru elementul respectiv | ||
| Line 1098: | Line 1105: | ||
| @Override | @Override | ||
| public boolean onCreateOptionsMenu(Menu menu) { | public boolean onCreateOptionsMenu(Menu menu) { | ||
| - | getMenuInflater().inflate(R.menu.main, menu); | + | getMenuInflater().inflate(R.menu.main, menu); |
| - | return true; | + | return true; |
| } | } | ||
| </code> | </code> | ||
| - | **2.** **programatic**, în codul sursă, de regulă în cadrul metodei ''onCreateOptionsMenu'' | + | **2.** **programatic**, în codul sursă, de regulă în cadrul metodei ''onCreateOptionsMenu()'' |
| Metodele prin intermediul cărora sunt adăugate intrări în cadrul meniului sunt: | Metodele prin intermediul cărora sunt adăugate intrări în cadrul meniului sunt: | ||
| <code java> | <code java> | ||
| Line 1132: | Line 1139: | ||
| @Override | @Override | ||
| public boolean onCreateOptionsMenu(Menu menu) { | public boolean onCreateOptionsMenu(Menu menu) { | ||
| - | MenuItem menuItem; | + | MenuItem menuItem; |
| | | ||
| - | SubMenu subMenu = menu.addSubMenu(GROUP_ID_NONE, SUBMENU_ID_OPERATIONS, MENU_ORDER, R.string.operations); | + | SubMenu subMenu = menu.addSubMenu(GROUP_ID_NONE, SUBMENU_ID_OPERATIONS, MENU_ORDER, R.string.operations); |
| - | menuItem = subMenu.add(GROUP_ID_NONE, MENU_ID_CREATE, MENU_ORDER, R.string.create); | + | menuItem = subMenu.add(GROUP_ID_NONE, MENU_ID_CREATE, MENU_ORDER, R.string.create); |
| - | menuItem.setIcon(R.drawable.create); | + | menuItem.setIcon(R.drawable.create); |
| - | menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); | + | menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); |
| - | // add other submenu entries | + | // add other submenu entries |
| | | ||
| - | menuItem = menu.add(GROUP_ID_GENERIC_ACTIONS, MENU_ID_SETTINGS, MENU_ORDER, R.string.settings); | + | menuItem = menu.add(GROUP_ID_GENERIC_ACTIONS, MENU_ID_SETTINGS, MENU_ORDER, R.string.settings); |
| - | menuItem.setIcon(R.drawable.settings); | + | menuItem.setIcon(R.drawable.settings); |
| - | menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); | + | menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); |
| - | // add other menu entries | + | // add other menu entries |
| | | ||
| - | menu.setGroupVisible(GROUP_ID_GENERIC_ACTIONS, true); | + | menu.setGroupVisible(GROUP_ID_GENERIC_ACTIONS, true); |
| - | menu.setGroupEnabled(GROUP_ID_GENERIC_ACTIONS, true); | + | menu.setGroupEnabled(GROUP_ID_GENERIC_ACTIONS, true); |
| - | menu.setGroupCheckable(GROUP_ID_GENERIC_ACTIONS, false, false); | + | menu.setGroupCheckable(GROUP_ID_GENERIC_ACTIONS, false, false); |
| | | ||
| - | menuItem = menu.add(GROUP_ID_NONE, MENU_ID_SETTINGS, MENU_ORDER, R.string.about); | + | menuItem = menu.add(GROUP_ID_NONE, MENU_ID_SETTINGS, MENU_ORDER, R.string.about); |
| - | menuItem.setIcon(R.drawable.about); | + | menuItem.setIcon(R.drawable.about); |
| - | menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); | + | menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); |
| - | // add other menu entries | + | // add other menu entries |
| | | ||
| - | return true; | + | return true; |
| } | } | ||
| </code> | </code> | ||
| Line 1161: | Line 1168: | ||
| Alte metode utile puse la dispoziție de clasa ''Menu'' sunt: | Alte metode utile puse la dispoziție de clasa ''Menu'' sunt: | ||
| - | * ''findItem(int)'' - întoarce un obiect de tip ''MenuItem'', dându-se identificatorul acestuia | + | * ''findItem(int)'' - întoarce un obiect de tip ''MenuItem'', dându-se identificatorul acestuia; |
| - | * ''getItem(int)'' - întoarce un obiect de tip ''MenuITem'', dându-se poziția acestuia | + | * ''getItem(int)'' - întoarce un obiect de tip ''MenuITem'', dându-se poziția acestuia; |
| - | * ''removeGroup(int)'' - șterge toate elementele din cadrul unui grup, furnizându-se identificatorul acestuia | + | * ''removeGroup(int)'' - șterge toate elementele din cadrul unui grup, furnizându-se identificatorul acestuia; |
| - | * ''clear()'' - șterge toate intrările intrărilor din cadrul meniului, acesta rămânând vid | + | * ''clear()'' - șterge toate intrările intrărilor din cadrul meniului, acesta rămânând vid; |
| - | * ''removeItem(int)'' - șterge o intrare din cadrul meniului, dându-se identificatorul acestuia | + | * ''removeItem(int)'' - șterge o intrare din cadrul meniului, dându-se identificatorul acestuia; |
| - | * ''size()'' - furnizează numărul de intrări din cadrul meniului | + | * ''size()'' - furnizează numărul de intrări din cadrul meniului; |
| - | * ''hasVisibleItems()'' - precizează dacă există intrări din cadrul meniului care sunt vizible sau nu | + | * ''hasVisibleItems()'' - precizează dacă există intrări din cadrul meniului care sunt vizible sau nu; |
| - | * ''close()'' - determină închiderea meniului, în cazul în care acesta este deschis | + | * ''close()'' - determină închiderea meniului, în cazul în care acesta este deschis. |
| <note tip>În situația în care sunt definite meniuri atât pentru activitate cât și pentru fragmentele pe care le conține, acestea sunt combinate, fiind incluse inițial opțiunile din activitate și ulterior acțiunile din fragmente, în ordinea în care acestea sunt declarate. De asemenea, se poate realiza și sortarea prin intermediul numărului de ordine definit de fiecare intrare propriu-zisă a meniului în parte.</note> | <note tip>În situația în care sunt definite meniuri atât pentru activitate cât și pentru fragmentele pe care le conține, acestea sunt combinate, fiind incluse inițial opțiunile din activitate și ulterior acțiunile din fragmente, în ordinea în care acestea sunt declarate. De asemenea, se poate realiza și sortarea prin intermediul numărului de ordine definit de fiecare intrare propriu-zisă a meniului în parte.</note> | ||
| Line 1175: | Line 1182: | ||
| ==== Tratarea evenimentelor asociate meniurilor ==== | ==== Tratarea evenimentelor asociate meniurilor ==== | ||
| + | |||
| Tratarea evenimentelor de accesare a unei intrări a meniului se face în cadrul metodei ''onOptionsItemSelected(MenuItem)'', apelată în mod automat în momentul producerii unui astfel de eveniment. Aceasta primește ca parametru opțiunea din cadrul meniului care a fost aleasă de utilizator, recunoașterea sa realizându-se prin intermediul identificatorului unic asociat fiecărei intrări: | Tratarea evenimentelor de accesare a unei intrări a meniului se face în cadrul metodei ''onOptionsItemSelected(MenuItem)'', apelată în mod automat în momentul producerii unui astfel de eveniment. Aceasta primește ca parametru opțiunea din cadrul meniului care a fost aleasă de utilizator, recunoașterea sa realizându-se prin intermediul identificatorului unic asociat fiecărei intrări: | ||
| Line 1180: | Line 1188: | ||
| @Override | @Override | ||
| public boolean onOptionsItemSelected(MenuItem item) { | public boolean onOptionsItemSelected(MenuItem item) { | ||
| - | switch(item.getItemId()) { | + | switch(item.getItemId()) { |
| - | case R.id.create: | + | case R.id.create: |
| - | case MENU_ID_CREATE: | + | case MENU_ID_CREATE: |
| - | // ... | + | // ... |
| - | return true; | + | return true; |
| - | // ... | + | // ... |
| - | } | + | } |
| - | return super.onOptionsItemSelected(item); | + | return super.onOptionsItemSelected(item); |
| } | } | ||
| </code> | </code> | ||
| Line 1199: | Line 1207: | ||
| <code java> | <code java> | ||
| public class CustomMenuItemClickListener implements MenuItem.OnMenuItemClickListener { | public class CustomMenuItemClickListener implements MenuItem.OnMenuItemClickListener { | ||
| - | @Override | + | @Override |
| - | public boolean onMenuItemClick(MenuItem item) { | + | public boolean onMenuItemClick(MenuItem item) { |
| - | switch(item.getItemId()) { | + | switch(item.getItemId()) { |
| - | case R.id.create: | + | case R.id.create: |
| - | case MENU_ID_CREATE: | + | case MENU_ID_CREATE: |
| - | // ... | + | // ... |
| - | return true; | + | |
| - | // ... | + | |
| - | } | + | |
| return true; | return true; | ||
| + | // ... | ||
| } | } | ||
| + | return true; | ||
| + | } | ||
| } | } | ||
| Line 1221: | Line 1229: | ||
| **2.** **utilizarea unei intenții asociate la o intrare din cadrul meniului** prin intermediul metodei ''setIntent(Intent)'', lansându-se în execuție activitatea corespunzătoare în condițiile în care: | **2.** **utilizarea unei intenții asociate la o intrare din cadrul meniului** prin intermediul metodei ''setIntent(Intent)'', lansându-se în execuție activitatea corespunzătoare în condițiile în care: | ||
| - | * nu este suprascrisă metoda de tratare a evenimentului de selectare a unei intrări din cadrul meniului ''onOptionsItemSelected()'' | + | * nu este suprascrisă metoda de tratare a evenimentului de selectare a unei intrări din cadrul meniului ''onOptionsItemSelected()''; |
| - | * în situația în care metoda de tratare a evenimentului de selectare a unei intrări din cadrul meniului ''onOptionsItemSelected()'' este suprascrisă, trebuie să se apeleze metoda părinte (''super.onOptionsItemSelected(menu)'') pentru acele intrări ale meniului ce nu sunt procesate | + | * în situația în care metoda de tratare a evenimentului de selectare a unei intrări din cadrul meniului ''onOptionsItemSelected()'' este suprascrisă, trebuie să se apeleze metoda părinte (''super.onOptionsItemSelected(menu)'') pentru acele intrări ale meniului ce nu sunt procesate. |
| În mod implicit, nici o intrare din cadrul unui meniu nu are asociată o intenție. | În mod implicit, nici o intrare din cadrul unui meniu nu are asociată o intenție. | ||
| Line 1229: | Line 1237: | ||
| === Meniuri contextuale === | === Meniuri contextuale === | ||
| + | |||
| Un //meniu contextual// (clasa [[http://developer.android.com/reference/android/view/ContextMenu.html|ContextMenu]]) este asociat de regulă unui control din cadrul interfeței grafice (spre diferență de meniurile de opțiuni care sunt asociate activităților). De regulă, acesta este accesat la operația de apăsare prelungită pe obiectul respectiv (de tip ''View''), având aceeași structură ca orice meniu, metodele utilizate pentru construirea sa fiind aceleași. | Un //meniu contextual// (clasa [[http://developer.android.com/reference/android/view/ContextMenu.html|ContextMenu]]) este asociat de regulă unui control din cadrul interfeței grafice (spre diferență de meniurile de opțiuni care sunt asociate activităților). De regulă, acesta este accesat la operația de apăsare prelungită pe obiectul respectiv (de tip ''View''), având aceeași structură ca orice meniu, metodele utilizate pentru construirea sa fiind aceleași. | ||
| Line 1242: | Line 1251: | ||
| @Override | @Override | ||
| public void onCreateContextMenu (ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { | public void onCreateContextMenu (ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { | ||
| - | super.onCreateContextMenu(menu, v, menuInfo); | + | super.onCreateContextMenu(menu, v, menuInfo); |
| - | // option 1 | + | // option 1 |
| - | MenuInflater inflater = getMenuInflater(); | + | MenuInflater inflater = getMenuInflater(); |
| - | inflater.inflate(R.menu.context_menu, menu); | + | inflater.inflate(R.menu.context_menu, menu); |
| - | // option 2 | + | // option 2 |
| - | menu.setHeaderTitle(R.string.operations); | + | menu.setHeaderTitle(R.string.operations); |
| - | menu.add(GROUP_ID_NONE, MENU_ID_CREATE, MENU_ORDER, R.string.create); | + | menu.add(GROUP_ID_NONE, MENU_ID_CREATE, MENU_ORDER, R.string.create); |
| } | } | ||
| </code> Metoda primește următorii parametri (ce pot fi utilizați pentru a se determina ce obiect din cadrul interfeței grafice a fost accesat, pentru a se instanția meniul contextual corespunzător): | </code> Metoda primește următorii parametri (ce pot fi utilizați pentru a se determina ce obiect din cadrul interfeței grafice a fost accesat, pentru a se instanția meniul contextual corespunzător): | ||
| - | * ''menu'' - meniul contextual care se dorește a fi afișat | + | * ''menu'' - meniul contextual care se dorește a fi afișat; |
| - | * ''view'' - elementul din cadrul interfeței grafice căruia îi este asociat meniul contextual | + | * ''view'' - elementul din cadrul interfeței grafice căruia îi este asociat meniul contextual; |
| - | * ''menuInfo'' - un obiect care oferă informații suplimentare cu privire la elementul selectat | + | * ''menuInfo'' - un obiect care oferă informații suplimentare cu privire la elementul selectat. |
| - implementarea metodei ''onContextItemSelected(MenuItem)'' care gestionează acțiunea de selectare a unei intrări din cadrul meniului contextual <code java> | - implementarea metodei ''onContextItemSelected(MenuItem)'' care gestionează acțiunea de selectare a unei intrări din cadrul meniului contextual <code java> | ||
| @Override | @Override | ||
| public boolean onContextItemSelected(MenuItem item) { | public boolean onContextItemSelected(MenuItem item) { | ||
| - | AdapterContextMenuInfo adapterContextMenuInfo = (AdapterContextMenuInfo)item.getMenuInfo(); | + | AdapterContextMenuInfo adapterContextMenuInfo = (AdapterContextMenuInfo)item.getMenuInfo(); |
| - | // or | + | // or |
| - | ExpandableContextMenuInfo expandableContextMenuInfo = (ExpandableContextMenuInfo)item.getMenuInfo(); | + | ExpandableContextMenuInfo expandableContextMenuInfo = (ExpandableContextMenuInfo)item.getMenuInfo(); |
| - | switch(item.getItemId()) { | + | switch(item.getItemId()) { |
| - | case R.id.create: | + | case R.id.create: |
| - | case MENU_ID_CREATE: | + | case MENU_ID_CREATE: |
| - | // ... | + | // ... |
| - | return true; | + | return true; |
| - | // ... | + | // ... |
| - | } | + | } |
| - | return super.onContextItemSelected(item); | + | return super.onContextItemSelected(item); |
| } | } | ||
| </code> Tratarea acțiunii de selectare a unei intrări din cadrul meniului contextual trebuie semnalată prin întoarcerea unui rezultat al metodei de tip ''true'', în caz contrar trebuind apelată metoda părinte ''super.onContextItemSelected(item)'' care va determina apelarea metodelor corespunzătoare eventualelor fragmente pe care le poate conține activitatea (în ordinea în care acestea au fost declarate) până în momentul în care una dintre acestea va întoarce un rezultat (implementarea implicită a metodei întoarce ''false'' atât pentru clasa ''Activity'' cât și pentru clasa ''Fragment''). | </code> Tratarea acțiunii de selectare a unei intrări din cadrul meniului contextual trebuie semnalată prin întoarcerea unui rezultat al metodei de tip ''true'', în caz contrar trebuind apelată metoda părinte ''super.onContextItemSelected(item)'' care va determina apelarea metodelor corespunzătoare eventualelor fragmente pe care le poate conține activitatea (în ordinea în care acestea au fost declarate) până în momentul în care una dintre acestea va întoarce un rezultat (implementarea implicită a metodei întoarce ''false'' atât pentru clasa ''Activity'' cât și pentru clasa ''Fragment''). | ||
| Line 1281: | Line 1290: | ||
| </code> O activitate poate fi invocată prin intermediul unui meniu contextual, dacă specifică valorile respective în câmpul ce indică filtrul pentru intenții în fișierul ''AndroidManifest.xml'': <code xml> | </code> O activitate poate fi invocată prin intermediul unui meniu contextual, dacă specifică valorile respective în câmpul ce indică filtrul pentru intenții în fișierul ''AndroidManifest.xml'': <code xml> | ||
| <intent-filter> | <intent-filter> | ||
| - | ... | + | ... |
| - | <category android:name="android.intent.category.ALTERNATIVE" /> | + | <category android:name="android.intent.category.ALTERNATIVE" /> |
| - | <category android:name="android.intent.category.SELECTED_ALTERNATIVE" /> | + | <category android:name="android.intent.category.SELECTED_ALTERNATIVE" /> |
| - | ... | + | ... |
| </intent-filter> | </intent-filter> | ||
| </code> | </code> | ||
| - căutarea unor activități care pot fi invocate folosind intenția respectivă prin intermediul metodei ''Menu.addIntentOptions'' (apelată pe obiectul transmis ca parametru metodei ''onCreateOptionsMenu()'') <code java> | - căutarea unor activități care pot fi invocate folosind intenția respectivă prin intermediul metodei ''Menu.addIntentOptions'' (apelată pe obiectul transmis ca parametru metodei ''onCreateOptionsMenu()'') <code java> | ||
| menu.addIntentOptions( | menu.addIntentOptions( | ||
| - | Menu.CATEGORY_ALTERNATIVE, // the group the contextual menu will be attached to | + | Menu.CATEGORY_ALTERNATIVE, // the group the contextual menu will be attached to |
| - | Menu.CATEGORY_ALTERNATIVE, // menu item ID for all of the menu items | + | Menu.CATEGORY_ALTERNATIVE, // menu item ID for all of the menu items |
| - | Menu.CATEGORY_ALTERNATIVE, // order number for each of the menu items | + | Menu.CATEGORY_ALTERNATIVE, // order number for each of the menu items |
| - | this.getComponentName(), // the name of the current activity | + | this.getComponentName(), // the name of the current activity |
| - | null, // no specific items to place with priority | + | null, // no specific items to place with priority |
| - | intent, // intent that can invoke the corresponding activities (previously defined) | + | intent, // intent that can invoke the corresponding activities (previously defined) |
| - | 0, // no additional flags to manage the menu items | + | 0, // no additional flags to manage the menu items |
| - | null); // no array of menu items to correlate with specific items | + | null); // no array of menu items to correlate with specific items |
| </code> Metoda furnizează o listă de activități care corespund criteriilor precizate de intenție populând cu acestea intrările din cadrul meniului, în cadrul unui anumit grup, alocându-le identificatori și numere de ordine începând cu o anumită valoare.\\ Semnătura metodei este: <code java> | </code> Metoda furnizează o listă de activități care corespund criteriilor precizate de intenție populând cu acestea intrările din cadrul meniului, în cadrul unui anumit grup, alocându-le identificatori și numere de ordine începând cu o anumită valoare.\\ Semnătura metodei este: <code java> | ||
| public abstract int addIntentOptions (int groupId, int itemId, int order, ComponentName caller, Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) | public abstract int addIntentOptions (int groupId, int itemId, int order, ComponentName caller, Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) | ||
| Line 1316: | Line 1325: | ||
| El se distinge însă față de celelalte tipuri de meniuri, față de care ar părea să implementeze o funcționalitate comună: | El se distinge însă față de celelalte tipuri de meniuri, față de care ar părea să implementeze o funcționalitate comună: | ||
| - | * spre diferență de meniurile de opțiuni, acesta este creat în mod manual și doar atunci când este accesat elementul căruia îi este atașat | + | * spre diferență de meniurile de opțiuni, acesta este creat în mod manual și doar atunci când este accesat elementul căruia îi este atașat; |
| - | * spre diferență de meniurile contextuale, acesta nu are nici un impact asupra controlului grafic căruia îi este atașat | + | * spre diferență de meniurile contextuale, acesta nu are nici un impact asupra controlului grafic căruia îi este atașat; |
| Un meniu de tip pop-up poate fi creat - ca orice meniu - atât prin intermediul unui fișier XML de resurse cât și programatic. | Un meniu de tip pop-up poate fi creat - ca orice meniu - atât prin intermediul unui fișier XML de resurse cât și programatic. | ||
| Line 1325: | Line 1334: | ||
| public void showPopupMenu(View view) { | public void showPopupMenu(View view) { | ||
| - | PopupMenu popupMenu = new PopupMenu(this, menu); | + | PopupMenu popupMenu = new PopupMenu(this, menu); |
| | | ||
| - | // option 1: defining a popup menu via a XML resource file | + | // option 1: defining a popup menu via a XML resource file |
| | | ||
| - | // android 3.0 | + | // android 3.0 |
| - | MenuInflater menuInflater = popupMenu.getMenuInflater(); | + | MenuInflater menuInflater = popupMenu.getMenuInflater(); |
| - | menuInflater.inflate(R.menu.popup_menu, popupMenu.getMenu()); | + | menuInflater.inflate(R.menu.popup_menu, popupMenu.getMenu()); |
| | | ||
| - | // android 4.0 | + | // android 4.0 |
| - | popupMenu.inflate(R.menu.popup_menu); | + | popupMenu.inflate(R.menu.popup_menu); |
| | | ||
| - | // option 2: defining a popup menu programatically | + | // option 2: defining a popup menu programatically |
| - | Menu menu = popupMenu.getMenu(); | + | Menu menu = popupMenu.getMenu(); |
| - | menu.add(GROUP_ID_NONE, MENU_ID_CREATE, MENU_ORDER, R.string.create); | + | menu.add(GROUP_ID_NONE, MENU_ID_CREATE, MENU_ORDER, R.string.create); |
| - | // ... | + | // ... |
| | | ||
| - | popup.show(); | + | popup.show(); |
| } | } | ||
| </code> | </code> | ||
| Line 1355: | Line 1364: | ||
| <code java> | <code java> | ||
| popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { | popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { | ||
| - | @Override | + | @Override |
| - | public boolean onMenuItemClick(MenuItem item) { | + | public boolean onMenuItemClick(MenuItem item) { |
| - | switch(item.getItemId()) { | + | switch(item.getItemId()) { |
| - | case R.id.create: | + | case R.id.create: |
| - | case MENU_ID_CREATE: | + | case MENU_ID_CREATE: |
| - | // ... | + | // ... |
| - | return true; | + | return true; |
| - | // ... | + | // ... |
| - | } | + | } |
| - | return true; | + | return true; |
| - | } | + | } |
| - | }); | + | }); |
| </code> | </code> | ||
| Line 1373: | Line 1382: | ||
| Se dorește implementarea unei aplicații Android care să afișeze lista tuturor contactelor din agenda telefonică, împreună cu unele informații despre aceștia (imaginea asociată, numele, numărul de accesări, cea mai recentă accesare, apartenența la grupul de favoriți). De asemenea, în momentul în care este selectat un element din listă, se vor afișa toate numerele telefonice și toate adresele de poștă electronică stocate cu privire la acesta, împreună cu tipul lor. Totodată, va exista o facilitate de căutare pe măsură ce se introduce un șir de caractere, care poate fi regăsit în oricare dintre detaliile contactului respectiv. | Se dorește implementarea unei aplicații Android care să afișeze lista tuturor contactelor din agenda telefonică, împreună cu unele informații despre aceștia (imaginea asociată, numele, numărul de accesări, cea mai recentă accesare, apartenența la grupul de favoriți). De asemenea, în momentul în care este selectat un element din listă, se vor afișa toate numerele telefonice și toate adresele de poștă electronică stocate cu privire la acesta, împreună cu tipul lor. Totodată, va exista o facilitate de căutare pe măsură ce se introduce un șir de caractere, care poate fi regăsit în oricare dintre detaliile contactului respectiv. | ||
| - | {{ :laboratoare:laborator05:addressbook.png?nolink&500 }} | + | {{ :laboratoare:laborator05:addressbook.png?nolink&400 }} |
| **0.** Se recomandă ca în situația în care se folosește un emulator, să se adauge în aplicația //People// cel puțin două contacte care să poată fi gestionate prin intermediul aplicației. | **0.** Se recomandă ca în situația în care se folosește un emulator, să se adauge în aplicația //People// cel puțin două contacte care să poată fi gestionate prin intermediul aplicației. | ||
| Line 1557: | Line 1566: | ||
| * adăugarea informațiilor referitoare la un contact (nume, numere de telefon, adrese de poștă electronică); | * adăugarea informațiilor referitoare la un contact (nume, numere de telefon, adrese de poștă electronică); | ||
| - | {{ :laboratoare:laborator05:insert_option.png?nolink&500 }} | + | {{ :laboratoare:laborator05:insert_option.png?nolink&400 }} |
| * editarea informațiilor referitoare la un contact selectat în listă (nu va fi posibilă adăugarea de alte numere de telefon / adrese de poștă electronică); | * editarea informațiilor referitoare la un contact selectat în listă (nu va fi posibilă adăugarea de alte numere de telefon / adrese de poștă electronică); | ||
| - | {{ :laboratoare:laborator05:update_option.png?nolink&500 }} | + | {{ :laboratoare:laborator05:update_option.png?nolink&400 }} |
| * ștergerea informațiilor referitoare la un contact selectat în listă. | * ștergerea informațiilor referitoare la un contact selectat în listă. | ||
| Line 1697: | Line 1706: | ||
| </code> | </code> | ||
| - | **7.** Să se realizeze o dispunere alternativă a listei de contacte din agenda telefonică, astfel încât pe rândurile pare respectiv pe rândurile impare, imaginea asociată unei persoane și pictograma indicând dacă aceasta a fost inclusă în lista de favoriți să apară dispuse în oglindă. | + | **7.** Să se realizeze o dispunere alternativă a listei de contacte din agenda telefonică, astfel încât pe rândurile pare respectiv pe rândurile impare, imaginea asociată unei persoane și pictograma indicând dacă aceasta a fost inclusă în lista de favoriți să fie aranjate invers. |
| + | |||
| + | {{ :laboratoare:laborator05:address_book_dispunere_alternativa.png?nolink&400 }} | ||
| * în directorul ''res/layout'' se vor defini două fișiere, ''contact_view_odd.xml'' și ''contact_view_even.xml'', conținând cele două moduri de dispunere diferită; | * în directorul ''res/layout'' se vor defini două fișiere, ''contact_view_odd.xml'' și ''contact_view_even.xml'', conținând cele două moduri de dispunere diferită; | ||
| Line 1801: | Line 1812: | ||
| ===== Resurse Utile ===== | ===== Resurse Utile ===== | ||
| - | [[http://ptgmedia.pearsoncmg.com/images/9780321940261/samplepages/0321940261.pdf|Joseph ANNUZZI, Jr, Lauren DARCEY, Shane CONDER, Introduction to Android Application Development - Developer's Library, 4th Edition, Addison-Wesley, 2013]] - capitolul 8, subcapitolele //Using Container Control Classes//, capitolul 17, subcapitolul //Menus//\\ | + | [[http://ptgmedia.pearsoncmg.com/images/9780321940261/samplepages/0321940261.pdf|Joseph ANNUZZI, Jr, Lauren DARCEY, Shane CONDER, Introduction to Android Application Development - Developer's Library, 4th Edition, Addison-Wesley, 2013]] - capitolul 8, subcapitolul //Using Container Control Classes//, capitolul 17, subcapitolul //Menus//\\ |
| [[http://www.bignerdranch.com/we-write/android-programming/|Bill PHILLIPS, Brian HARDY, Android Programming. The Big Nerd Ranch Guide, Pearson Technology Group, 2013]] - capitolele 9, 16\\ | [[http://www.bignerdranch.com/we-write/android-programming/|Bill PHILLIPS, Brian HARDY, Android Programming. The Big Nerd Ranch Guide, Pearson Technology Group, 2013]] - capitolele 9, 16\\ | ||
| - | [[http://www.amazon.com/Professional-Android-4-Application-Development/dp/1118102274|Reto MEIER, Professional Android for Application Development, John Wiley & Sons, 2012]] - capitolul 4 (//The Android Widget Toolbok//, //Introducing Adapters//), 10 (//Configuring Action Bar Icon Navigation Behavior//)\\ | + | [[http://www.amazon.com/Professional-Android-4-Application-Development/dp/1118102274|Reto MEIER, Professional Android for Application Development, John Wiley & Sons, 2012]] - capitolele 4 (//The Android Widget Toolbok//, //Introducing Adapters//), 10 (//Configuring Action Bar Icon Navigation Behavior//)\\ |
| [[http://books.google.ro/books/about/The_Android_Developer_s_Cookbook.html?id=Y4JR2yI2Fo0C&redir_esc=y|Ronan SCHWARZ, Phil DUTSON, James STEELE, Nelson TO, Android Developer's Cookbook, Building Applications with the Android SDK, 2nd Edition, Addison Wesley, 2013]] - capitolele 6, 7\\ | [[http://books.google.ro/books/about/The_Android_Developer_s_Cookbook.html?id=Y4JR2yI2Fo0C&redir_esc=y|Ronan SCHWARZ, Phil DUTSON, James STEELE, Nelson TO, Android Developer's Cookbook, Building Applications with the Android SDK, 2nd Edition, Addison Wesley, 2013]] - capitolele 6, 7\\ | ||
| [[http://eu.wiley.com/WileyCDA/WileyTitle/productCd-1118199545.html|Wei Meng LEE, Beginning Android 4 Application Development, Wiley, 2012]]\\ | [[http://eu.wiley.com/WileyCDA/WileyTitle/productCd-1118199545.html|Wei Meng LEE, Beginning Android 4 Application Development, Wiley, 2012]]\\ | ||
