2013-05-02 39 views
4

我正在實現一個ListActivity和ListFragment,並希望允許用戶使用短點擊和長點擊 - 短暫編輯/顯示該項目的詳細信息,然後長按以彈出一個上下文菜單並帶有刪除選項該項目。但是,我似乎無法觸發onCreateContextMenu。 onListItemClick工作正常,並捕獲所有的水龍頭,無論短期還是長期。 ListFragment使用稍微自定義的SimpleCursorAdaptor和LoaderManager來填充,而不是使用佈局文件。Android ListFragment:如何讓onListItemClick和onContextItemSelected?

是可能有兩個?

代碼...

LocationsListFragment.java 

package com.level3.connect.locations; 

//import removed for 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; 

// the activity attaching to this fragment should implement this interface 
public interface OnLocationSelectedListener { 
    public void onLocationSelected(String locationId); 
}  

@Override 
public void onCreate(Bundle savedInstanceState) { 

    super.onCreate(savedInstanceState); 

    // Fields from the database (projection) 
    // Must include the _id column for the adapter to work 
    String[] from = new String[] { LocationsTable.LOCATION_NAME, 
      LocationsTable.LOCATION_PHONE_NAME }; 
    // Fields on the UI to which we map 
    int[] to = new int[] { R.id.titleText, R.id.phoneText }; 

    // connect to the 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 is called fine 
    return root; 
} 

// hook up listening for the user selecting a location in the 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 a location - show a detailed view - this 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 - this is 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 - this is 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 a new loader after the 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 is not available anymore, delete reference 
    adapter.swapCursor(null); 
} 

} 

更新:我還沒有想通了這一點,我想知道,如果我不得不放棄這一策略,並在其他一些實現它,而不是用戶友好的方式。也許滑動查看細節和點擊刪除?

回答

4

我在原生電子郵件應用程序的Android源代碼中找到了我的答案。 https://android.googlesource.com/platform/packages/apps/Email/

的ListFragment必須實現監聽器:

public class MessageListFragment extends SherlockListFragment 
    implements LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemLongClickListener 

    private static final int DELETE_ID = Menu.FIRST + 1;  

    private SimpleCursorAdapter adapter; 

    // The LoaderManager needs initializing 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 

     super.onCreate(savedInstanceState); 

     // Fields from the database (projection) 
     // Must include the _id column for the adapter to work 
     String[] from = new String[] { BookmarksTable.BOOKMARK_NAME, 
      BookmarksTable.BOOKMARK_PHONE_NAME }; 
     // Fields on the UI to which we map 
     int[] to = new int[] { R.id.titleText, R.id.phoneText }; 

     // connect to the database 
     getLoaderManager().initLoader(0, null, this); 
     adapter = new BookmarkCursorAdapter(getActivity(), 
      R.layout.bookmark_row, null, from, to, 0); 

     setListAdapter(adapter); 
    } 

    // register to put up the context menu 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 
     View root = super.onCreateView(inflater, container, savedInstanceState); 
     registerForContextMenu(root); 
     return root; 
    } 

    // set the listeners for long click 
    @Override 
    public void onViewCreated(View view, Bundle savedInstanceState) { 
     super.onViewCreated(view, savedInstanceState); 
     getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); 
     getListView().setOnItemLongClickListener(this); 
    } 

的調用的方法是:

/** 
    * Called when a message is clicked. 
    */ 
@Override 
public void onListItemClick(ListView parent, View view, int position, long id) { 
     // do item click stuff; show detailed view in my case 

} 


@Override 
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { 
    return false; // let the system show the 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 to the 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); 
} 

爲了完整起見,這裏的加載程序代碼

// Loader code 
// Creates a new loader after the 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 is not available anymore, delete reference 
    adapter.swapCursor(null); 
} 
相關問題