views:

946

answers:

2

I'm attempting to use a ContextMenu.
I've successfully done this for a simple ListActivity using SimpleCursorAdapter.
Moving on I want to replace SimpleCursorAdapter with CursorAdapter but still retain the ContextMenu behaviour, so I've added the two mandatory override functions bindView and newView

public View newView(Context context, Cursor cursor, ViewGroup parent) {
    View view = mLayoutInflater.inflate(R.layout.check_row, parent, false);
    registerForContextMenu(view);
    return view;
}

Note the registerForContextMenu which replaces the registerForContextMenu(getListView()) in the onCreate method of the ListActivity. I found this necessary to get a call to onCreateContextMenu(...)

All this works (rows created with the expected widgets, callbacks on them working etc etc). All that is except that the ContextMenuInfo parameter supplied to onCreateContextMenu(...) is now null - stopping me accessing the rowId.
Is there another trick to perform - perhaps in the bindView(...) method of the CursorAdapter?

+1  A: 

That's not the right approach. You register the context menu for the ListView, not the rows. Call registerForContextMenu() up front, perhaps in onCreate() after you inflate the layout.

CommonsWare
I want to put registerForContextMenu() in onCreate() but doing so results in the list entries not responding to long clicking - so there is no call to onCreateContextMenu() and thus no context menus.Putting the register newView() results in a callback to onCreateContextMenu() - but now the ContextMenuInfo parameter is null. However - having the register in both newView() and onCreate() works insomuch as onCreateContextMenu() is called with a valid entry in ContextMenuInfo.I don't believe this is 'right', there must be a better way?
Gray-M
"I want to put registerForContextMenu() in onCreate() but doing so results in the list entries not responding to long clicking - so there is no call to onCreateContextMenu() and thus no context menus." Check out http://github.com/commonsguy/cw-android/tree/master/Database/Constants/ for a sample of ListView and registerForContextMenu().
CommonsWare
Thanks. I took this sample and attempted to recreate my issue here rather than in my own code - and aha! Modify row.xml to have a CheckBox and ContextMenus are no longer available. You don't need any logic to handle CheckBox, just add the following at the end of row.xml <CheckBox android:layout_below="@id/value" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/check" android:layout_toLeftOf="@+id/value" />
Gray-M
You could try using a CheckedTextView instead, which is the officially supported way of putting checkboxes in ListView rows. Give it the android:id of @android:id/text1 and Android should even handle it via CHOICE_MODE_SINGLE.
CommonsWare
Good call - this is simpler and does allow context menu to work 'out of the box'. However it does present problems setting the initial checked state from a dB Cursor (which I've yet to resolve)
Gray-M
+2  A: 

I'm answering the question - but I would point out that 'commonsware.com' provided the clues and direction, see above.
The problem
- Using CheckBox in the row layout impacts upon the use of Context menus
- CheckedTextView is, I believe, intended for multi-selection, it doesn't lend itself to initialization of the checked state.

The solution I adopted does the following
1. Use CheckedTextView
2. Extend from CursorAdapter to initialize the checked state during bindView(...)
Note: This must manage displaying the correct icons too
3. Manage the CheckedTextView's state in onListItemClick(...) and record it in the dBase, not forgetting to update the cursor.

Gray-M