2010-05-28 11 views
9

En Android, onContextItemSelected tiene un único argumento MenuItem, por lo que no está claro cómo identificar la vista seleccionada. MenuItem.getMenuInfo proporciona acceso a Contextmenu.ContextMenuInfo, pero aunque ambas subclases conocidas proporcionan acceso a la vista de destino, no parece haber un descriptor de acceso en la interfaz.Identificación de la vista seleccionada en un ContextMenu (Android)

Una alternativa es guardar el View proporcionada en onCreateContextMenu en una variable de clase privada que se basa en onCreateContextMenu no ser llamado de nuevo en la actividad antes de onContextItemSelected. Otra es utilizar la identificación del View para el argumento itemId de ContextMenu.add. Si hacemos esto, entonces necesitaríamos identificar la opción seleccionada del menú contextual usando su título (posiblemente internacionalizado).

¿Cuál es el mejor método para identificar el View seleccionado en onContextSelected?

+0

Vea también: http://stackoverflow.com/questions/2321332/detecting-which-selected-item-in-a-listview-spawned-the-contextmenu-android –

Respuesta

9

No existe el concepto de "identificación de la vista seleccionada" para los menús de opciones o los menús contextuales en Android. Por lo tanto, es bastante difícil responder a su pregunta. Entonces, tomaré algunas conjeturas.

Si por "la identificación de la vista seleccionada" quiere decir que la elección de menú seleccionado, es decir getItemId() en el MenuItem que se pasa a onOptionsItemSelected() o onContextItemSelected().

Si por "la identificación de la vista seleccionada" quiere decir qué fila en un ListView fue el de un largo tapping para que aparezca el menú contextual, fundido getMenuInfo() (llamado en el MenuItem) a AdapterView.AdapterContextMenuInfo, use el id o los valores position según corresponda según su adaptador. See here for a sample project que usa esta técnica.

Si al "identificar la Vista seleccionada" quiere decir que tiene más de un menú contextual que no es ListView en una actividad, no usaría esa técnica de IU.

+0

Quise decir la tercera opción, que en general hay podría haber varias vistas en la pantalla y que algunas de ellas podrían querer tener el mismo menú contextual. ¿Por qué no usarías esa técnica de UI? – Casebash

+1

Simple: no hay indicaciones visuales para los menús contextuales. Un pequeño porcentaje de usuarios de Android sabe que debe tocar las listas para menús contextuales. Al lado de nadie, se molestará en tratar de tocar largamente cualquier otra cosa para los menús contextuales. Todo lo que ofreces a través de los menús contextuales debe ser ofrecido por al menos otro mecanismo, solo para una mejor visibilidad. Los usuarios avanzados pueden encontrar los menús contextuales 'ListView', por lo que ofrecerlos para acelerar la navegación está bien. ¿Menús contextuales en otras cosas que no sean 'ListViews'? Simplemente no me molestaría. – CommonsWare

+0

Buenos puntos, pero olvidó responderme @. Supongamos que tiene que usar múltiples menús contextuales. ¿Qué método usarías? – Casebash

6

El objetivo de un menú contextual es que esté asociado a una vista subyacente individual, y es claramente una limitación de diseño en Android que la asociación se pierda en la devolución de llamada 'onContextItemSelected'. Habilitar el tacto largo en cualquier vista de tamaño suficiente parece perfectamente razonable como una alternativa al clic derecho del mouse.

Como han recomendado otros mensajes, para algunos contextos:

AdapterView.AdapterContextMenuInfo menuInfo = 
(AdapterView.AdapterContextMenuInfo)item.getMenuInfo(); 

es apropiado y el TargetView es un punto de referencia útil.

Otra forma es subclasificar la vista y anular 'getContextMenuInfo' para proporcionar la referencia de la vista. Por ejemplo, un TextView simple:

 
package ...; 

public class TextViewWithContext extends TextView { 
    TextViewContextMenuInfo _contextMenuInfo = null; 

    public TextViewWithContext(Context context) { 
     super(context); 
     _contextMenuInfo = new TextViewContextMenuInfo(this); 
    } 

    public TextViewWithContext(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     _contextMenuInfo = new TextViewContextMenuInfo(this); 
    } 

    protected ContextMenuInfo getContextMenuInfo() { 
     return _contextMenuInfo; 
    } 

    public boolean isContextView(ContextMenuInfo menuInfo) { 
     return menuInfo == (ContextMenuInfo)_contextMenuInfo; 
    } 

    protected class TextViewContextMenuInfo implements ContextMenuInfo { 
     protected TextView _textView = null; 

     protected TextViewContextMenuInfo(TextView textView) { 
      _textView = textView; 
     } 
    } 
} 

... 
    @Override 
    public boolean onContextItemSelected(MenuItem item) { 

     ContextMenuInfo menuInfo = item.getMenuInfo(); 

     if (textViewWithContext.isContextView(menuInfo) { 
      ... 
     } 
    } 

Por último, habría sido más útil si la clase base Ver había asignado un objeto ContextInfo con una referencia inversa a la vista, en lugar de nulo como en la actualidad.

+0

He preparado una aplicación de muestra con este enfoque: http://ogrelab.ikratko.com/identifying-the-view-selected-in-a-contextmenu-in-oncontextitemselected-method/ – Ognyan

2

TestActivity clase extiende Actividad {

// create temp item here 

private ImageView tmpImageView = null; 

...

public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo){ 
    super.onCreateContextMenu(menu, v, menuInfo); 
    // initialize temp item 
    mCurrentStatusImage = (ImageView) v.findViewById(R.id.rule_status); 
} 

public boolean onContextItemSelected(MenuItem item) { 
    switch (item.getItemId()) { 
     case ENABLE_ID: 
      // use temp item 
      tmpImageView.setImageResource(android.R.drawable.presence_online); 
      return super.onContextItemSelected(item); 
     case DISABLE_ID: 
      // use temp item 
      tmpImageView.setImageResource(android.R.drawable.presence_invisible); 
      return super.onContextItemSelected(item); 
     default:  
      return super.onContextItemSelected(item); 
} 
1

que fija un problema similar al establecer un ID de grupo para la Menultem basado en el elemento que lo envió por ejemplo:

textview.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() { 
     @Override 
     public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) { 
       menu.setHeaderTitle("Context Menu"); 
       menu.add(R.id.whateverviewclicked, RENAME_MENU_ITEM, 0, "Rename"); 
       menu.add(R.id.whateverviewclicked, DELETE_MENU_ITEM, 1, "Delete"); 
      } 
     }); 

Esto permitirá obtener el ID de grupo en el onContextItemSelected:

public boolean onContextItemSelected(MenuItem aItem) { 
     int selectedViewID = aItem.getGroupId(); 
     int selectedItem = aItem.getItemId(); 
}; 

no tiene que usar la ID del recurso; puede usar cualquier int que desee. ¡Funciona para mi!

1

En caso de que esté asociando ContextMenus a múltiples Vistas que NO están en un ListView (es decir, no hay un adaptador subyacente a las Vistas) y desea determinar qué Vista se presionó para acceder al ContextMenu, el siguiente "hackeo" puede ser implementado. (Sería mejor si Android proporcionara un oyente que podría asociarse con cada elemento).

El "piratear" es que uno crea un miembro de vista privada mLastViewTouched en la clase y luego adjuntar los siguientes onTouchListener a todas las vistas que pueden generar un contextMenu

private View.OnTouchListener onTouchListener = new View.OnTouchListener() { 
    @Override 
    public boolean onTouch(View view, MotionEvent motionEvent) 
    { 
     mLastViewTouched = view;  // Store a handle on the last view touched. This will be used to identify the view on which the Context Menu was launched 

     return false;  // We return false since this indicates that the touch was not handled and so it is passed down the stack to be handled appropriately 
    } 
}; 

Así que cada vez que una vista es tocado mLastViewTouched es actualizado. Ahora, en onContextItemSelected, tendrá acceso a la Vista que inició el ContextMenu.

0

Al construir su menú en OnCreateContextMenuListener o public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) aplicación, se puede establecer una costumbre MenuItem.OnMenuItemClickListener para cada elemento:

addPhotosBtn.setOnCreateContextMenuListener((menu, v, menuInfo) -> { 
     getMenuInflater().inflate(R.menu.upload_image_menu, menu); 
     int itemCount = menu.size(); 
     for(int i = 0; i < itemCount; i++) { 
      menu.getItem(i).setOnMenuItemClickListener(addPhotosBtnMenuItemClickListener); 
     } 
    }); 

Dado que en este momento se tiene acceso a la vista para la que va a crear el menú contextual, puedes unir estrechamente al oyente con esa vista.

Cuestiones relacionadas