2010-05-28 2 views
9

In Android hat onContextItemSelected ein einzelnes MenuItem-Argument und daher ist nicht klar, wie die ausgewählte Ansicht zu identifizieren ist. MenuItem.getMenuInfo bietet Zugriff auf Contextmenu.ContextMenuInfo, aber während beide bekannten Unterklassen Zugriff auf die Zielansicht bereitstellen, scheint kein Accessor auf der Schnittstelle zu sein.Identifizieren der in einem ContextMenu (Android) ausgewählten Ansicht

Eine Alternative ist die View vorgesehen in onCreateContextMenu in einem privaten Klassenvariablen zu speichern, die auf verlässt sich onCreateContextMenu nicht wieder vor onContextItemSelected der Tätigkeit genannt zu werden. Ein anderer ist die Verwendung der ID View für das itemId Argument von ContextMenu.add. Wenn wir dies tun, müssen wir dann die ausgewählte Option aus dem Kontext-Menü identifizieren, indem wir ihren (möglicherweise internationalisierten) Titel verwenden.

Was ist die beste Methode zur Identifizierung der View ausgewählt in onContextSelected?

+0

Siehe auch: http://stackoverflow.com/questions/2321332/detecting-which-selected-item-in-a-listview-spawned-the-contextmenu-android –

Antwort

9

Es gibt kein solches Konzept wie "Identifizieren der ausgewählten Ansicht" für Optionsmenüs oder Kontextmenüs in Android. Daher ist es ziemlich schwierig, Ihre Frage zu beantworten. Also, ich nehme ein paar Vermutungen an.

Wenn durch „die Ansicht Identifizierung ausgewählt“ Sie bedeuten, die Menüwahl gewählt wurde, ist, dass getItemId() auf dem MenuItem, die onOptionsItemSelected() oder onContextItemSelected() geben wird.

Wenn durch „die Ansicht Identifizierung ausgewählt“ Sie bedeuten, welche Zeile in eine ListView war derjenige lang geklopft, um das Kontextmenü aufzurufen, werfen getMenuInfo() (genannt auf dem MenuItem) zu AdapterView.AdapterContextMenuInfo, dann verwenden Sie entweder die id oder Die position Werte entsprechen Ihrem Adapter. See here for a sample project, die diese Technik verwendet.

Wenn Sie unter "Auswählen der ausgewählten Ansicht" meinen, dass Sie mehr als ein Kontextmenü in einer Aktivität haben, würde ich diese UI-Technik nicht verwenden.

+0

Ich meinte die dritte Option, die im Allgemeinen dort Es könnte sich um mehrere Ansichten auf dem Bildschirm handeln und einige von ihnen möchten möglicherweise dasselbe Kontextmenü haben. Warum würden Sie diese UI-Technik nicht verwenden? – Casebash

+1

Einfach: Es gibt keine visuellen Hinweise für Kontextmenüs. Ein kleiner Prozentsatz der Android-Nutzer weiß, dass sie lange auf Listen für Kontextmenüs tippen müssen. Neben niemandem wird es einen Versuch geben, lange auf etwas anderes für Kontextmenüs zu tippen. Alles, was Sie über Kontextmenüs anbieten, muss von mindestens einem anderen Mechanismus zur besseren Auffindbarkeit angeboten werden. Hauptbenutzer finden möglicherweise die 'ListView'-Kontextmenüs, und daher bietet es sich an, diese zu verwenden, um die Navigation zu beschleunigen. Kontextmenüs zu anderen Dingen als 'ListViews'? Ich würde mich einfach nicht kümmern. – CommonsWare

+0

Gute Punkte, aber Sie haben vergessen, mich zu erinnern. Angenommen, Sie müssten mehrere Kontextmenüs verwenden. Welche Methode würden Sie verwenden? – Casebash

6

Der ganze Punkt eines Kontextmenüs ist, dass es mit einer individuellen zugrundeliegenden Ansicht verbunden ist, und es ist eindeutig eine Designbeschränkung in Android, dass die Assoziation in dem Rückruf 'onContextItemSelected' verloren ist. Das Aktivieren von Long-Touch bei jeder Ansicht von ausreichender Größe erscheint als Alternative zu einem rechten Mausklick durchaus sinnvoll.

Wie andere Beiträge haben für manche Kontexte empfohlen,:

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

angemessen ist und die Target ist ein nützlicher Bezugspunkt.

Eine andere Möglichkeit besteht darin, die Ansicht zu untergliedern und 'getContextMenuInfo' zu überschreiben, um die Ansichtsreferenz bereitzustellen. Zum Beispiel kann eine einfache Textview:

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

Schließlich wäre es hilfreicher, wenn die Basis View-Klasse ein ContextInfo Objekt mit einem umgekehrten Bezug auf die Ansicht zugewiesen hatte, anstatt null wie derzeit.

+0

Ich habe eine Beispiel-App mit diesem Ansatz vorbereitet: http://ogrelab.ikratko.com/identifying-the-view-selected-in-a-contextmenu-in-concontextitemselected-method/ – Ognyan

2

Klasse TestActivity erstreckt Aktivität {

// 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

Ich reparierte ein ähnliches Problem, indem ein groupID für die MenuItem basierend auf welches Element Einstellung gesendet es zB:

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

Dies würde ermöglichen es Ihnen, die groupID im onContextItemSelected zu erhalten:

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

Sie müssen nicht die Ressourcen-ID verwenden - Sie können einen beliebigen int verwenden. Funktioniert bei mir!

1

Wenn Sie ContextMenus an mehrere Views anhängen, die sich NICHT in einem ListView befinden (dh es gibt keinen Adapter, der den Views zugrunde liegt) und Sie möchten feststellen, welche View lange gedrückt war, um auf das ContextMenu zuzugreifen kann implementiert werden. (Es wäre besser, wenn Android einen Listener bereitstellt, der jedem Element zugeordnet werden kann).

Der „Hack“ ist, dass man mLastViewTouched in der Klasse ein eigenes Mitglied erstellt und dann die folgenden onTouchListener alle Ansichten anschließen, die eine ContextMenu erzeugen:

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

Also, wenn eine Ansicht berührt wird mLastViewTouched ist aktualisiert. Jetzt in onContextItemSelected haben Sie Zugriff auf die Ansicht, die das ContextMenu initiiert hat.

0

Wenn Ihr Menü in OnCreateContextMenuListener oder public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) Implementierung Konstruieren Sie eine benutzerdefinierte MenuItem.OnMenuItemClickListener für jedes Element festlegen:

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

Da zu diesem Zeitpunkt haben Sie Zugriff auf die Ansicht, für die Sie über das Kontextmenü erstellen, Sie können den Hörer eng mit dieser Ansicht verbinden.

Verwandte Themen