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.
- Eliminar un oyente de una vista en android
- ¿Cómo detectar pulsaciones de teclas de caracteres?
- Custom ListAdapter consistente en EditText pierde el foco llamado dos veces
- Android getOnTouchListener con la versión del API> = 15
- Cómo hacer clic o tocar en un texto de TextView
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); } });
- Cómo establecer el evento onClick en un ImageButton?
- ¿Cómo detectar cuando el usuario pulsa la tecla "menú" en su dispositivo Android?
- ¿Por qué mi onItemSelectedListener no se llama en un ListView?
- Android: implementa el receptor de difusión para ClipboardManager
- Establecer oyente de clic largo para listview
- Manejar varios oyentes de clic de botón
- Cómo detectar los eventos de MediaPlayer de youtube desde un servicio
- Establecer un oyente personalizado para escuchar en toda la aplicación
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; } });
- Escuchar en una vista si la vista cambia su posición XY
- Sube la foto de la cámara y el archivador de archivos desde el campo INPUT de la vista web