【问题标题】:Android GridView OnItemLongClick listener called after OnItemClick在 OnItemClick 之后调用的 Android GridView OnItemLongClick 侦听器
【发布时间】:2013-03-29 17:13:35
【问题描述】:

基本上我想在用户短按或长按网格视图中的单元格时显示不同的上下文菜单。我遇到的问题是,如果用户短按 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);      

            }
        });

【问题讨论】:

    标签: android gridview contextmenu listener onitemclicklistener


    【解决方案1】:

    我了解您希望为 GridView 项目的短按和长按显示不同的上下文菜单。

    首先,您只需为短按设置监听器,因为默认行为会在长按时自动显示上下文菜单。

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

    最后,在 onCreateContextMenu() 中检查是否为短按并显示不同的上下文菜单(标准)并将标志设置为 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

    【讨论】:

    • 这完全解决了我的问题。我所要做的就是完全删除 onItemLongClick 侦听器,只需使用以下代码在 onContextItemSelected() 中获取选定的单元格:
    • AdapterView.AdapterContextMenuInfo info=(AdapterView.AdapterContextMenuInfo)item.getMenuInfo(); mSelectedCell = (myCellClass) info.targetView;
    【解决方案2】:

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

    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”。

    【讨论】:

    • !不起作用,因为代码在侦听器之外,它只会在设置侦听器时执行,而不是在实际执行时执行。我的布局是动态设置的,并且在创建布局时我已经在代码中设置了这些属性。还是谢谢。
    【解决方案3】:

    您可以覆盖调度事件侦听器,该侦听器负责长点击处理

    【讨论】:

      【解决方案4】:
      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{} 
      
      }
      

      【讨论】:

      • 显然行不通。到达该代码时,clickFlag 从未被修改过。
      【解决方案5】:

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

      【讨论】:

      • 我试过这个,但由于某种原因,它会导致一些奇怪的行为,onItemLongClick 被反复调用,似乎无休止,似乎我的网格视图中的每个单元格都可能调用一次。我绝对不明白它在做什么。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-22
      • 2014-09-14
      • 1970-01-01
      • 2014-04-20
      相关资源
      最近更新 更多