Obsah Menu Ikonkové Rozšířené Submenu Kontextové ListView ListActivity Adapter BaseAdapter ArrayAdapter CursorAdapter SimpleCursorAdapter 2
3 Menu Možnost jak rychle přistupovat k funkcím aplikace bez obětování cenného prostoru na obrazovce Aktivita může mít vlastní menu, které se objeví po stisknutí tlačítka menu Android také podporuje kontextové menu, což je v podstatě náhrada stisku pravého tlačítka na PC Kontextové menu jsou běžně zobrazena po dlouhém podržení trackpadu(, trackballu, všesměrného tlačítka ) nebo prstu na vybraném View Menu podporují submenu, checkboxy, radio tlačítka klávesové zkratky a ikonky
Ikonkové menu Objeví se na spodní straně obrazovky po stisknutí tlačítka menu Pro omezený počet položek (většinou 6) zobrazí ikonku a text (zbytek se schová do více) Nezobrazuje checkboxy, radio buttony ani klávesové zkratky Měl by se dodržovat styl ikonek popsaný na http://developer.android. com 4
Rozšířené menu Vysune se po stisku tlačítka více v ikonkovém menu Zobrazí scrollovatelný seznam těch položek, které se nevešly do ikonkového menu Zobrazují se checkboxy, radio buttony, plná délka popisku Nezobrazují se však ikonky Nelze vynutit zobrazení rozšířeného menu! S checkboxama a radio buttonama se tudíž musí zacházet opatrně Maximální počet položek v ikonkovém menu se liší zařízení od zařízení 5
Submenu Zobrazí se po kliknutí na položku obsahující v sobě další menu Jméno položky se objeví v titulku dialogu Nelze vložit submenu do submenu Stejné chování jako u rozšířeného menu (checkboxy, radio buttony, žádné ikonky ) 6
7 Menu Po stisku HW tlačítka menu se v aktivitě zavolá metoda oncreateoptionsmenu, která je třeba přepsat Jako parametr obdržíme Menu, do kterého přidáme položky Můžeme použít MenuInflater a naplnit menu položkami z XML(res/menu/main_menu.xml) a/nebo je přidat ručně 1. @Override 2. public boolean oncreateoptionsmenu(menu menu) { 3. 4. 5. //naplneni menu z res/menu/main_menu.xml MenuInflater inflater = getmenuinflater(); inflater.inflate(r.menu.main_menu, menu); 6. 7. 8. 9. 10. //rucni pridani polozky int groupid = Menu.NONE;//skupina(pouzivana pro radio buttony) nas nezajima int itemid = 55;//ID polozky, bude nas zajimat v onoptionsitemselected int order = Menu.NONE;//poradi polozky nas nezajima menu.add(groupid, itemid, order, "Polozka").setIcon(R.drawable.icon); 11. 12. 13. 14. //rucni odebrani polozky menu.removeitem(55); return super.oncreateoptionsmenu(menu);
8 Menu res/menu/main_menu.xml 1. <?xml version="1.0" encoding="utf-8"?> 2. <menu xmlns:android="http://schemas.android.com/apk/res/android"> 3. 4. 5. 6. <!-- Normalni polozka s ikonkou --> <item android:id="@+id/item1" android:title="normalni polozka" android:icon="@drawable/icon" /> 7. 8. 9. 10. <!-- Checkbox --> <item android:checkable="true" android:id="@+id/groupitem1" android:title="checkbox" /> 11. 12. 13. 14. 15. 16. 17. <!-- Skupina radio buttonu --> <group android:checkablebehavior="single"> <item android:id="@+id/radio1" android:title="radio button 1" /> <item android:id="@+id/radio1" android:title="radio button 2" /> </group> 18. <!-- Submenu --> 19. <item android:id="@+id/submenu" 20. android:title="submenu"> 21. <menu> 22. <item android:id="@+id/submenuitem11" 23. android:title="polozka submenu" /> 24. 25. </menu> 26. </item> 27.</menu>
9 Menu Po vybrání položky z menu se zavolá metoda onoptionsitemselected, která dostane v atributu vybranou položku - MenuItem 1. @Override 2. public boolean onoptionsitemselected(menuitem item) { 3. switch (item.getitemid()) { 4. case R.id.item1: 5.... 6. break; 7. case R.id.radio1: 8.... 9. break; 10. case R.id.submenuItem11: 11.... 12. break; 13. 14. return super.onoptionsitemselected(item); 15.
10 Menu Metoda oncreateoptionsmenu se zavolá pouze před prvním vytvořením menu Pokud potřebujeme menu dynamicky měnit, je třeba tak činit v onprepareoptionsmenu, které se zavolá před každým vyjetím menu Při zavírání menu se volá onoptionsmenuclosed
11 Kontextové menu Analogie pro kliknutí pravým tlačítkem myši na PC Zobrazeny po dlouhém podržení daného View nebo zavoláním View.createContextMenu(menu) Podobné jako Submenu Dané View se musí zaregistrovat na použití kontextového menu pomocí registerforcontextmenu(view); Pro zobrazení menu je třeba přepsat metodu oncreatecontextmenu(contextmenu, View, ContextMenuInfo) Implementace podobná jako u oncreateoptionsmenu(menu); Atribut View View které uživatel vybral Atribut ContextMenuInfo podrobnosti o kontextovém menu Pro provedení akce po výběru položky z menuje třeba přepsat oncontextitemselected(menuitem); Stejné jako onoptionsitemselected(menuitem);
Kontextové menu příklad 1. 2. 3. 4. 5. 6. @Override protected void oncreate(bundle savedinstancestate) {... registerforcontextmenu(view);... 1. 2. 3. 4. 5. 6. 7. @Override public void oncreatecontextmenu(contextmenu menu, View v, ContextMenuInfo menuinfo) { MenuInflater inflater = getmenuinflater(); inflater.inflate(r.menu.context_menu, menu); super.oncreatecontextmenu(menu, v, menuinfo); 1. @Override 2. public boolean oncontextitemselected(menuitem item) { 3. switch (item.getitemid()) { 4. case R.id.new_game: 5. newgame(); 6. return true; 7. default: 8. return super.oncontextitemselected(item); 9. 10. 12
ListView Potomek AdapterView View pro zobrazení vertikálního posunovatelného seznamu Položkami ListView mohou být i komplikované View Možnost přidání hlavičky a zápatí addheaderview(view v) public void addfooterview (View v) Pro práci s ním je dobré používat ListActivity (ale není nutností) 13
14 ListActivity Activita obsahující právě jeden ListView Není nutné nastavovat layout vzhledu Ale je to i možné, layout poté musí obsahovat jedno ListView s id android:id="@android:id/list Obsahuje ListAdapter Adapter Most mezi AdapterView a zobrazovanými daty Zodpovědný za vytváření View pro každou položku datové kolekce Využívá se při vkládání položek do ListView, Spinner, ViewPager, AutoCompleteTextView aj.
15 BaseAdapter Abstraktní třída Základní stavební kámen pro tvorbu vlastních adaptéru ArrayAdapter Generická třída BaseAdapter umožňující vložení pole (array) libovolných prvků Každá položka je pouze TextView, proto je každý vložený prvek interpretován pomocí metody tostring() daného objektu CursorAdapter BaseAdapter umožňující vložení kurzoru (Cursor)
16 ListActvity za použití ArrayAdapteru public class MyList extends ListActivity { public void oncreate(bundle icicle) { super.oncreate(icicle); String[] names = new String[] { "Linux", "Windows 7", "Eclipse", "Suse", "Ubuntu", "Solaris", "Android", "iphone"; this.setlistadapter(new ArrayAdapter<String>(this, android.r.layout.simple_list_item_1, names)); @Override protected void onlistitemclick(listview l, View v, int position, long id) { super.onlistitemclick(l, v, position, id); Object o = this.getlistadapter().getitem(position); String keyword = o.tostring(); Toast.makeText(this, "You selected: " + keyword, Toast.LENGTH_LONG).show();
17 Výsledek ListActivity s ArrayAdapterem
18 ListActivity s vlastním layoutem položky layout/rowlayout.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_vertical"> <ImageView android:id="@+id/icon" android:layout_height="wrap_content" android:src="@drawable/icon" android:layout_width="22dp" android:layout_margintop="4dp" android:layout_marginright="4dp" android:layout_marginleft="4dp"> </ImageView> <TextView android:text="@+id/textview01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/label" android:textsize="30dp"></textview> </LinearLayout> rowlayout.xml nastavíme nově vytvořenému adaptéru: this.setlistadapter(new ArrayAdapter<String>(this, R.layout.rowlayout, R.id.label, names));
Výsledek ListActivity s vlastním layoutem položky 19
20 Vlastní ArrayAdapter public class MyArrayAdapter extends ArrayAdapter<String> { private final Activity context; private final String[] names; public MyArrayAdapter(Activity context, String[] names) { super(context, R.layout.rowlayout, names); this.context = context; this.names = names; Zabránění přístupu k metodám a parametrům nadtřídy static class ViewHolder { public ImageView imageview; public TextView textview; Drží jednotlivé View vlastního layoutu položky a při použití View.getTag() není nutné často volat časově náročnější operaci findviewbyid(int)
21 Vlastní ArrayAdapter - pokračování @Override public View getview(int position, View convertview, ViewGroup parent) { ViewHolder holder; Recyklace existujícího View View rowview = convertview; if (rowview == null) { LayoutInflater inflater = context.getlayoutinflater(); rowview = inflater.inflate(r.layout.rowlayout, null, true); holder = new ViewHolder(); holder.textview = (TextView) rowview.findviewbyid(r.id.label); holder.imageview = (ImageView) rowview.findviewbyid(r.id.icon); rowview.settag(holder); else { holder = (ViewHolder) rowview.gettag(); holder.textview.settext(names[position]); String s = names[position]; if (s.startswith("windows 7") s.startswith("iphone") s.startswith("solaris")) { holder.imageview.setimageresource(r.drawable.no); else { holder.imageview.setimageresource(r.drawable.ok); return rowview; getview() vrací jednu položku Adaptéru (seznamu)
22 Výsledek vlastního ArrayAdapteru
23 Zobrazení různých vlastních layoutů položek @Override public View getview(int position, View convertview, ViewGroup parent) { View rowview = convertview; if (rowview == null) { if (getitemviewtype(position) == 0) { rowview = inflator.inflate(r.layout.row_even, null); else { rowview = inflator.inflate(r.layout.row_odd, null); ViewHolder viewholder = new ViewHolder(); viewholder.text = (TextView) rowview.findviewbyid(r.id.textview01); viewholder.image = (ImageView) rowview.findviewbyid(r.id.imageview01); rowview.settag(viewholder); ViewHolder holder = (ViewHolder) rowview.gettag(); holder.text.settext(values[position]); return rowview;
24 SimpleCursorAdapteru Mapuje sloupce z Cursoru do jednotlivých View Příklad Získání Cursoru kontaktů: private Cursor getcontacts() { Uri uri = ContactsContract.Contacts.CONTENT_URI; String[] projection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME ; String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '" + ("1") + "'"; String[] selectionargs = null; String sortorder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; return managedquery(uri, projection, selection, selectionargs, sortorder);
25 Příklad SimpleCursorAdapteru pokračování @Override Context public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); Cursor mcursor = getcontacts(); startmanagingcursor(mcursor); ListAdapter adapter = new SimpleCursorAdapter(this, android.r.layout.two_line_list_item, Pole potřebných mcursor, sloupců new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME, new int[] { android.r.id.text1, android.r.id.text2 ); setlistadapter(adapter); ID View odpovídajících daným sloupcům v layoutu položky
26 Aktualizace položek v Adaptéru notifydatasetchanged() Funguje u ArrayAdapter Nastavený List<T> objects v kontruktoru Adaptéru nesmí být nahrazen jiným List<T> objects Vhodné použít metody clearall() a addall() nad List<T> objects cursor.requery() Lze volat nad Cursorem vloženým do CursorAdapteru
27 choicemode v ListView none singlechoice Pouze jedna položka stavu chosen state multiplechoice Více položek stavu chosen state multiplechoicemodal Více položek stavu chosen state podle vlastního výběru Implementací AbsListView.MultiChoiceModeListener Za použití setmultichoicemodelistener(abslistview.multichoic emodelistener)
28 Filtrace ListView Adaptéru je možné doimplementovat Filterable V mětodě getfilter() je poté nutné vrátit vlastní Filter Filter musí implementovat metody performfiltering() a publishresults() ArrayAdapter Má již implementovaný vlastní ArrayFilter, který filtruje položky List<T> objects podle metody tostring() objektu T ArrayFilter je dobrou inspirací pro vlastní filtrování