在OnItemClick之后调用的Android GridView OnItemLongClick侦听器

时间:2013-03-29 17:13:35

标签: android gridview contextmenu listener onitemclicklistener

基本上我想在用户点击或长按网格视图中的单元格时显示不同的上下文菜单。我遇到的问题是,如果用户短暂点击OnItemClick监听器被调用,我看到调试器到达显示上下文菜单的代码,而不是从那里移动到onCreateContextMenu,它转到onItemLongClick。

我尝试使用布尔值来阻止正在执行的长按代码,这会阻止执行代码,但即使这样做,onCreateContextMenu也不会被调用。

如果我删除了onItemLongClick侦听器,则短暂的单击侦听器可以正常工作,并且正确显示上下文菜单。

我知道其他人也提出类似的问题,但我仍然无法找到有效的解决方案。如果有人能解决这个问题或指出我正确的方向,请提前告知我们。赏金将颁发给任何能够指出我正确方向的人。

这是听众代码的简化版本:

        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 个答案:

答案 0 :(得分:7)

我知道您希望在GridView项目上显示短按和长按的不同上下文菜单。

首先,您只需设置侦听器以进行短暂点击,因为默认行为会在长时间点击时自动显示上下文菜单。

接下来,在OnItemClickListener中将布尔标志设置为true。长按一下,默认值为false。

最后,在onCreateContextMenu()中检查它是否短按并显示不同的上下文菜单(标准)并将flag设置为false。否则,让它显示默认的上下文菜单(选项)。

以下是一些展示这个想法的代码。

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]);
        }
    }   
}

示例应用: 您可以下载示例应用程序以查看行为。 GridExample_eclipse_project

答案 1 :(得分:0)

对于绝望的情况绝望的解决方案。

1.尝试使用布尔值,而不是在侦听器中执行代码。

 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检查布局中的clickable和longclickable属性是否都为“true”。

答案 2 :(得分:0)

您可以覆盖负责长按处理的调度事件侦听器

答案 3 :(得分:0)

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{} 

}

答案 4 :(得分:0)

OnItemLongClickListener被触发,因为显示ListView的上下文菜单将尝试通过该侦听器执行此操作。以下是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;
}

由此可以看出,如果mOnItemLongClickListener.onItemLongClick返回true,则表示调用已处理且方法退出。如果它返回false,则它会尝试创建上下文菜单。

因此,您需要在onItemLongClick(您的代码未显示)中修改您的return语句,如果真的长时间点击,则返回 true false 如果刚刚点击:

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;
    }
});