4

В принципе, я хочу показать другое контекстное меню, когда пользователь щелкает или долго нажимает на ячейку в виде сетки. Проблема заключается в том, что если пользователь коротких кликов вызывает прослушиватель OnItemClick, и я вижу, что отладчик достигает кода, который показывает контекстное меню, а не перемещается оттуда в onCreateContextMenu, он переходит в onItemLongClick.Android GridView OnItemLongClick прослушиватель, вызванный после OnItemClick

Я попытался использовать логическое значение, чтобы предотвратить выполнение кода длинного клика, который предотвращает выполнение этого кода, однако даже когда это делается 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);  

      } 
     }); 

ответ

7

Я понимаю, вы хотите, чтобы показать другое контекстное меню для коротких щелчков и длинных кликов на GridView пункта.

Во-первых, вам просто нужно установить прослушиватель для короткого клика, поскольку по умолчанию поведение автоматически отображает контекстное меню при длительных щелчках.

Затем установите флажок Boolean в значение true в OnItemClickListener. Значение по умолчанию для длинных кликов - false.

Наконец, в onCreateContextMenu() проверьте, есть ли у него короткий клик и отобразите другое контекстное меню (стандартное) и установите флаг в false. Else позволяет отображать контекстное меню по умолчанию (опции).

Вот какой код для демонстрации идеи.

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

+0

Это полностью решило мою проблему. Все, что мне нужно было сделать, это полностью удалить прослушиватель onItemLongClick и просто использовать следующий код, чтобы получить выбранную ячейку в onContextItemSelected(): – collusionbdbh

+0

AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); \t mSelectedCell = (myCellClass) info.targetView; – collusionbdbh

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 «истинными» в вашем макете.

+0

! не работает, поскольку код находится вне слушателя, он будет выполняться только при настройке слушателей, а не при их фактическом выполнении. Мой макет динамически настроен, и я уже установил эти свойства в коде при создании макета. Спасибо, в любом случае. – collusionbdbh

0

Вы можете overide отправки прослушивателя события, который resposible долгого клика обработки

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

} 
+0

явно не работает. clickFlag никогда не изменялся при достижении этого кода. – njzk2

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 возвращает истину, то это означает, что вызов был обработан и выходит метод.Если он возвращает false, то он пытается создать контекстное меню.

Таким образом, вы должны изменить свое обратное заявление в onItemLongClick (что ваш код не отображается), чтобы вернуть истинную, если это было действительно долго щелкнули, и ложные, если он просто нажал:

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

Я пробовал это и по какой-то причине приводит к некоторому странному поведению, onItemLongClick вызывается многократно и, казалось бы, бесконечно, кажется, что он может быть вызван один раз для каждой ячейки в моем представлении сетки. Я определенно не понимаю, что он делает. – collusionbdbh