Android GridView OnItemLongClick escuchador llamado después de OnItemClick

Básicamente, quiero mostrar un menú de contexto diferente cuando el usuario hace clic corto o hace clic largo en una celda en la vista de cuadrícula. El problema que tengo es que si el usuario hace clic corta el oyente OnItemClick se llama y veo el depurador llegar al código que muestra el menú contextual, pero en lugar de pasar de allí a onCreateContextMenu va a onItemLongClick.

He intentado usar un Boolean para prevenir el código largo del tecleo que es ejecutado que evita que el código que es ejecutado, no obstante incluso cuando esto se hace onCreateContextMenu no se llama en absoluto.

Si elimino el listener onItemLongClick, el oyente de clic corto funciona correctamente y el menú contextual se muestra correctamente.

Sé que otras personas han hecho preguntas similares a esto, pero todavía no he podido encontrar una solución que funcione. Si alguien puede resolver esto o apuntarme en la dirección correcta por favor hágamelo saber, gracias de antemano. Bounty se otorgará a cualquiera que pueda incluso señalarme en la dirección correcta.

Esta es una versión simplificada del código para los oyentes:

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

Entiendo que desea mostrar diferentes menús contextuales para clics cortos y clics largos en un elemento GridView.

En primer lugar, sólo tiene que establecer el oyente para hacer clic, ya que el comportamiento predeterminado mostrará automáticamente el menú contextual en los clics largos.

A continuación, establezca un indicador booleano como true en OnItemClickListener. El valor predeterminado es false para los clics largos.

Por último, en onCreateContextMenu () compruebe si es un clic corto y mostrar un menú de contexto diferente (estándar) y establecer el indicador a falso. Deje que muestre el menú contextual predeterminado (opciones).

Aquí hay un código para demostrar la 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]); } } } 

Ejemplo de aplicación : puede descargar una aplicación de ejemplo para ver el comportamiento. GridExample_eclipse_project

Para situaciones desesperadas soluciones desesperadas.

1. Intente trabajar con booleanos, en lugar de ejecutar código dentro de los oyentes.

  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 Compruebe si las propiedades de clic y de longclickable son "verdaderas" en su diseño.

Usted puede overide despachador de eventos de envío que es resposible para el manejo de clic largo

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

OnItemLongClickListener se dispara porque mostrar el menú contextual de un ListView intentará hacerlo a través de ese oyente. Aquí está el código de 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; } 

A partir de esto, podemos ver que si mOnItemLongClickListener.onItemLongClick devuelve true, entonces significa que la llamada fue manejada y el método sale. Si devuelve false, intenta crear el menú contextual.

Por lo tanto, debe modificar su declaración de devolución en onItemLongClick (que su código no está mostrando) para devolver true si se ha hecho clic durante largo tiempo, y false si acaba de hacer clic en:

 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; } }); 
  • Android getOnTouchListener con la versión del API> = 15
  • Audiencia de eventos personalizada en la aplicación para Android
  • ¿Es posible que cuando haga clic edittext mostrará mensaje de diálogo?
  • Cómo implementar OnZoomListener en MapView
  • ¿Por qué ButterKnife usa un DebouncingOnClickListener para los métodos de @OnClick?
  • Evento de incendio en AsyncTask finalizado
  • Android View.OnKeyListener: haga clic una vez, ejecute dos veces
  • Manejar varios oyentes de clic de botón
  • Evento de desencadenamiento cuando AsyncTask se completa con Listener
  • ¿Cómo detectar pulsaciones de teclas de caracteres?
  • Contando Chars en EditText Changed Listener
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.