Android ListFragment: how to have both onListItemClick and onContextItemSelected? -
i'm implementing listactivity , listfragment , allow user use short taps , long taps - short being edit/show details of item , long tap bring context menu option delete item. don't seem able trigger oncreatecontextmenu, however. onlistitemclick works fine , captures taps, short or long. listfragment populated using custom simplecursoradaptor , loadermanager, not using layout file.
is possible have both?
code...
locationslistfragment.java package com.level3.connect.locations; //import removed brevity public class locationslistfragment extends sherlocklistfragment implements loadermanager.loadercallbacks<cursor>{ private static final int delete_id = menu.first + 1; private simplecursoradapter adapter; private onlocationselectedlistener locationselectedlistener; // activity attaching fragment should implement interface public interface onlocationselectedlistener { public void onlocationselected(string locationid); } @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); // fields database (projection) // must include _id column adapter work string[] = new string[] { locationstable.location_name, locationstable.location_phone_name }; // fields on ui map int[] = new int[] { r.id.titletext, r.id.phonetext }; // connect database getloadermanager().initloader(0, null, this); adapter = new locationcursoradapter(getactivity(), r.layout.location_row, null, from, to, 0); setlistadapter(adapter); } @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { view root = super.oncreateview(inflater, container, savedinstancestate); registerforcontextmenu(root); //this called fine return root; } // hook listening user selecting location in list @override public void onattach(activity activity) { super.onattach(activity); try { locationselectedlistener = (onlocationselectedlistener) activity; } catch (classcastexception e) { throw new classcastexception(activity.tostring() + " must implement onlocationselectedlistener"); } } // handle user tapping location - show detailed view - works fine @override public void onlistitemclick(listview l, view v, int position, long id) { string projection[] = { locationstable.key_id }; cursor locationcursor = getactivity().getcontentresolver().query( uri.withappendedpath(databasecontentprovider.content_uri, string.valueof(id)), projection, null, null, null); if (locationcursor.movetofirst()) { string locationurl = locationcursor.getstring(0); locationselectedlistener.onlocationselected(locationurl); } locationcursor.close(); } // context menu - never called @override public void oncreatecontextmenu(contextmenu menu, view v, contextmenuinfo menuinfo) { super.oncreatecontextmenu(menu, v, menuinfo); menu.add(0, delete_id, 0, r.string.menu_delete); } @override - never called public boolean oncontextitemselected(android.view.menuitem item) { switch (item.getitemid()) { case delete_id: adaptercontextmenuinfo info = (adaptercontextmenuinfo) item .getmenuinfo(); uri uri = uri.parse(databasecontentprovider.content_uri + "/" + info.id); getactivity().getcontentresolver().delete(uri, null, null); return true; } return super.oncontextitemselected(item); } // loader code // creates new loader after initloader () call @override public loader<cursor> oncreateloader(int id, bundle args) { string[] projection = { locationstable.key_id, locationstable.location_name, locationstable.location_phone_name }; cursorloader cursorloader = new cursorloader(getactivity(), databasecontentprovider.content_uri, projection, null, null, null); return cursorloader; } @override public void onloadfinished(loader<cursor> loader, cursor data) { adapter.swapcursor(data); } @override public void onloaderreset(loader<cursor> loader) { // data not available anymore, delete reference adapter.swapcursor(null); } }
update: still have not figured out , wondering if have abandon strategy , implement in other, not user-friendly manner. perhaps swipe view details , tap delete?
i've found answer in android source code native email app. https://android.googlesource.com/platform/packages/apps/email/
the listfragment must implement listeners:
public class messagelistfragment extends sherlocklistfragment implements loadermanager.loadercallbacks<cursor>, adapterview.onitemlongclicklistener private static final int delete_id = menu.first + 1; private simplecursoradapter adapter; // loadermanager needs initializing @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); // fields database (projection) // must include _id column adapter work string[] = new string[] { bookmarkstable.bookmark_name, bookmarkstable.bookmark_phone_name }; // fields on ui map int[] = new int[] { r.id.titletext, r.id.phonetext }; // connect database getloadermanager().initloader(0, null, this); adapter = new bookmarkcursoradapter(getactivity(), r.layout.bookmark_row, null, from, to, 0); setlistadapter(adapter); } // register put context menu @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { view root = super.oncreateview(inflater, container, savedinstancestate); registerforcontextmenu(root); return root; } // set listeners long click @override public void onviewcreated(view view, bundle savedinstancestate) { super.onviewcreated(view, savedinstancestate); getlistview().setchoicemode(listview.choice_mode_single); getlistview().setonitemlongclicklistener(this); }
the called methods are:
/** * called when message clicked. */ @override public void onlistitemclick(listview parent, view view, int position, long id) { // item click stuff; show detailed view in case } @override public boolean onitemlongclick(adapterview<?> parent, view view, int position, long id) { return false; // let system show context menu } // context menu @override public void oncreatecontextmenu(contextmenu menu, view v, contextmenuinfo menuinfo) { super.oncreatecontextmenu(menu, v, menuinfo); menu.add(0, delete_id, 0, r.string.menu_delete); } // respond context menu tap @override public boolean oncontextitemselected(android.view.menuitem item) { switch (item.getitemid()) { case delete_id: adaptercontextmenuinfo info = (adaptercontextmenuinfo) item .getmenuinfo(); uri uri = uri.parse(databasecontentprovider.bookmark_id_uri + long.tostring(info.id)); getactivity().getcontentresolver().delete(uri, null, null); return true; } return super.oncontextitemselected(item); }
for completeness, here's loader code
// loader code // creates new loader after initloader () call @override public loader<cursor> oncreateloader(int id, bundle args) { string[] projection = { bookmarkstable.key_id, bookmarkstable.bookmark_name, bookmarkstable.bookmark_phone_name }; cursorloader cursorloader = new cursorloader(getactivity(), databasecontentprovider.bookmarks_uri, projection, null, null, null); return cursorloader; } @override public void onloadfinished(loader<cursor> loader, cursor data) { adapter.swapcursor(data); } @override public void onloaderreset(loader<cursor> loader) { // data not available anymore, delete reference adapter.swapcursor(null); }
Comments
Post a Comment