Android GridView OnItemLongClick listener called a

2019-03-31 01:01发布

Basically I want to show a different context menu when the user short clicks or long clicks on a cell in the grid view. The issue I have is that if the user short clicks the OnItemClick listener is called and I see the debugger reach the code that shows the context menu but rather than moving from there to onCreateContextMenu it goes to onItemLongClick.

I have tried using a Boolean to prevent the long click code being executed which does prevent that code being executed, however even when this is done onCreateContextMenu is not called at all.

If I remove the onItemLongClick listener the short click listener works correctly and the context menu is shown correctly.

I know other people have asked questions similar to this but I still haven't been able to find a solution that works. If anyone can solve this or point me in the right direction please let me know, thanks in advance. Bounty will be awarded to anyone who can even point me in the right direction.

This is a simplified version of the code for the listeners:

        mTGrid.setOnItemClickListener(new OnItemClickListener() {
            //this listener should show the context menu for a short click on the gridview.
            @Override
            public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
                    mRequiredMenu = "standard";
                    parent.showContextMenuForChild(v);      

            }
        });

        mTGrid.setOnItemLongClickListener(new OnItemLongClickListener() {
            //this listener should show the context menu for a long click on the gridview.
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View v, int position, long id) {
                    mRequiredMenu = "options";
                        parent.showContextMenuForChild(v);      

            }
        });

5条回答
狗以群分
2楼-- · 2019-03-31 01:20
mTGrid.setOnItemClickListener(new OnItemClickListener() {
            //this listener should show the context menu for a short click on the gridview.
            @Override
            public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
                     clickFlag=true;   
                     mRequiredMenu = "standard";                     

            }
        });

        mTGrid.setOnItemLongClickListener(new OnItemLongClickListener() {
            //this listener should show the context menu for a long click on the gridview.
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View v, int position, long id) {
                     clickFlag=false;
                     mRequiredMenu = "options";                  
            }
        });

if(clickFlag){        
    if(mRequiredMenu.equals("standard");{
        //just click event
        parent.showContextMenuForChild(v);
    }else{}
}else{
   if(mRequiredMenu.equals("options");{
        //just Long click event
        parent.showContextMenuForChild(v);
    }else{} 

}
查看更多
做个烂人
3楼-- · 2019-03-31 01:21

For desperate situation desperate solutions.

1.Try to work with booleans, instead of executing code inside the listeners.

 mTGrid.setOnItemClickListener(new OnItemClickListener() {
        //this listener should show the context menu for a short click on the gridview.
        @Override
        public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
                b=true     
        }
    });

    mTGrid.setOnItemLongClickListener(new OnItemLongClickListener() {
        //this listener should show the context menu for a long click on the gridview.
        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View v, int position, long id) {
                b=false      
        }
    });
if(b)
{
     mRequiredMenu = "standard";
     parent.showContextMenuForChild(v);  
}
else
{
    mRequiredMenu = "options";
    parent.showContextMenuForChild(v);
}

2 check if both of clickable and longclickable properties are "true" in your layout.

查看更多
Bombasti
4楼-- · 2019-03-31 01:27

OnItemLongClickListener gets triggered because showing the context menu for a ListView will attempt to do so through that listener. Here's the code from AbsListView:

@Override
public boolean showContextMenuForChild(View originalView) {
    final int longPressPosition = getPositionForView(originalView);
    if (longPressPosition >= 0) {
        final long longPressId = mAdapter.getItemId(longPressPosition);
        boolean handled = false;

        if (mOnItemLongClickListener != null) {
            handled = mOnItemLongClickListener.onItemLongClick(AbsListView.this, originalView,
                    longPressPosition, longPressId);
        }
        if (!handled) {
            mContextMenuInfo = createContextMenuInfo(
                    getChildAt(longPressPosition - mFirstPosition),
                    longPressPosition, longPressId);
            handled = super.showContextMenuForChild(originalView);
        }

        return handled;
    }
    return false;
}

From this, we can see that if mOnItemLongClickListener.onItemLongClick returns true, then that signifies that the call was handled and the method exits. If it returns false, then it attempts to create the context menu.

So you need to modify your return statement in onItemLongClick (which your code isn't showing) to return true if it was really long clicked, and false if it was just clicked:

mTGrid.setOnItemClickListener(new OnItemClickListener() {

    @Override
    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {

        mRequiredMenu = "standard";
        mItemClicked = true;
        parent.showContextMenuForChild(v);
    }
});

mTGrid.setOnItemLongClickListener(new OnItemLongClickListener() {

    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View v, int position, long id) {

        if(mItemClicked) {
            mItemClicked = false;
            return false;
        }

        mRequiredMenu = "options";
        parent.showContextMenuForChild(v);
        return true;
    }
});
查看更多
We Are One
5楼-- · 2019-03-31 01:33

You can overide dispatch event listener which is resposible for long click handling

查看更多
Rolldiameter
6楼-- · 2019-03-31 01:42

I understand you want to show different context menu for short clicks and long clicks on a GridView item.

First, you just need to set listener for short click since the default behavior will automatically show context menu on long clicks.

Next, set a boolean flag to true in the OnItemClickListener. The default value is false for long clicks.

Finally, in onCreateContextMenu() check if its a short click and show a different context menu (standard) and set flag to false. Else let it show the default context menu (options).

Here is some code to demonstrate the idea.

public class MainActivity extends Activity {

    private static final String[] arr = {"A", "B", "C", "D", "E", "F", "G", "H","I"};

    private GridView mTGrid;
    private boolean isShort;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mTGrid = (GridView) findViewById(R.id.gridView1);
        registerForContextMenu(mTGrid);

        mTGrid.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                isShort = true;
                openContextMenu(view);
            }
        });

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.cell, arr);
        mTGrid.setAdapter(adapter);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;

        if(isShort) {
            getMenuInflater().inflate(R.menu.context_standard, menu);
            menu.setHeaderTitle("Standard Menu for "+arr[info.position]);
            isShort = false;
        }
        else {
            getMenuInflater().inflate(R.menu.context_options, menu);
            menu.setHeaderTitle("Options Menu for "+arr[info.position]);
        }
    }   
}

Sample Application: You can download a sample application to see the behavior. GridExample_eclipse_project

查看更多
登录 后发表回答