My app used to use a standard ListView, and registerForContextMenu(getListView()) and everything worked just fine.
I needed to change my app to accommodate nested lists so I replaced the ListView with ExpandableListView. I changed the Activity to ExpandableListActivity. I also changed my adapter to a tree adapter and implemented a custom view class to populate the list with (based on a LinearLayout viewgroup).
I have been trying to track down where I screwed it up and I've found several things.
The most important is that when I add a longclick listener to my custom view and return false from it, my context menu pops up and functions properly. However, I don't get the fading orange-to-white long click animation because the long click is being sucked up somewhere else until it is handled by a longclicklistener and ignored (thus being thrown back up the chain until it reaches the ExpandableListView (which is registered for context menus).
I am using a TouchInterceptor model to handle certain gestures from my listview with the following implementation:
public class TouchInterceptor extends ExpandableListView {
...
protected MotionEvent downStart = null;
public boolean onInterceptTouchEvent(MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
// keep track of the starting down-event
downStart = MotionEvent.obtain(event);
break;
case MotionEvent.ACTION_MOVE:
// if moved horizontally more than slop*2, capture the event for ourselves
if(downStart == null)
{
break;
}
float deltaX = event.getX() - downStart.getX();
if(Math.abs(deltaX) > ViewConfiguration.getTouchSlop() * 2)
return true;
break;
}
// otherwise let the event slip through to children
return super.onInterceptTouchEvent(event);
}
public boolean onTouchEvent(MotionEvent event) {
// check if we crossed an item
if(downStart != null)
{
float targetWidth = this.getWidth() / 4;
float deltaX = event.getX() - downStart.getX(),
deltaY = event.getY() - downStart.getY();
boolean movedAcross = (Math.abs(deltaX) > targetWidth);
boolean steadyHand = (Math.abs(deltaX / deltaY) > 2);
if(movedAcross && steadyHand) {
boolean crossRight = (deltaX > 0);
// figure out which child view we crossed
ListView list = (ListView)this.findViewById(android.R.id.list);
int position = list.pointToPosition((int)downStart.getX(), (int)downStart.getY());
// pass crossed event to any listeners
onCross(crossRight, position);
downStart = null;
// and return true to consume this event
return true;
}
}
return super.onTouchEvent(event);
}
... }
Is there something wrong with how I'm handling these events?
Note: although my context menu pops up, it only does so when the long-click event is triggered, not a long OK button click.
Something is screwed up here and I'm not sure how to track it down.