57 votes

Détecter quel élément sélectionné (dans un ListView) a généré le ContextMenu (Android)

J'ai une ListView qui permettra à l'utilisateur appuyez longuement sur un élément pour obtenir un menu contextuel. Le problème, je vais avoir, c'est dans la détermination ListItem ils ont très-pressé. J'ai essayé de faire ceci:

myListView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
  @Override public void onCreateContextMenu(ContextMenu menu, final View v, ContextMenuInfo menuInfo) {
   menu.add("Make Toast")
    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
     @Override public boolean onMenuItemClick(MenuItem item) {
      String toastText = "You clicked position " + ((ListView)v).getSelectedItemPosition();
      Toast.makeText(DisplayScheduleActivity.this, toastText, Toast.LENGTH_SHORT).show();
      return true;
     }
    });
  } 
 });

mais il se bloque jusqu'à ce qu'une ANR pop-up. Je soupçonne qu'après le menu est créé l' ListItem n'est plus sélectionnée.

Il semble que vous pouvez surveiller pour les clics ou de longue clics, puis d'enregistrer l'élément cliqué là:

 mArrivalsList.setOnItemLongClickListener(new OnItemLongClickListener() {
  @Override public boolean onItemLongClick(AdapterView<?> parent, View v, int position, long id) {
   // record position/id/whatever here
   return false;
  }
 });

mais qui se sent majorly kludgey pour moi. Quelqu'un at-il de meilleures solutions pour cela?

76voto

Eric Burke Points 2893

- Je faire exactement cela. Dans mon onCreateContextMenu(...) la méthode, j'ai jeté le ContextMenu.ContextMenuInfo à AdapterView.AdapterContextMenuInfo. À partir de là, vous pouvez obtenir le targetView, vous lancez de nouveau pour le widget. Le code complet est disponible dans HomeActivity.java, regardez pour les onCreateContextMenu(...) de la méthode.

@Override
public void onCreateContextMenu(ContextMenu contextMenu,
                                View v,
                                ContextMenu.ContextMenuInfo menuInfo) {
    AdapterView.AdapterContextMenuInfo info =
            (AdapterView.AdapterContextMenuInfo) menuInfo;
    selectedWord = ((TextView) info.targetView).getText().toString();
    selectedWordId = info.id;

    contextMenu.setHeaderTitle(selectedWord);
    contextMenu.add(0, CONTEXT_MENU_EDIT_ITEM, 0, R.string.edit);
    contextMenu.add(0, CONTEXT_MENU_DELETE_ITEM, 1, R.string.delete);
}

Notez que je stocke le texte sélectionné ainsi que de la select id dans les champs privés. Depuis l'INTERFACE utilisateur est thread-clos, je sais que le selectedWord et selectedWordId champs sera correct pour des actions ultérieures.

67voto

Daniel Lew Points 39063

Tout d'abord, je me demandais si vous faites les choses un peu trop compliqué en utilisant View.setOnCreateContextMenuListener(). Les choses deviennent beaucoup plus facile si vous utilisez Activity.registerForContextMenu(), parce que vous pouvez simplement utiliser Activity.onCreateContextMenu() et Activity.onContextItemSelected() pour gérer l'ensemble de votre menu événements. Cela signifie essentiellement que vous n'avez pas à définir tous ces anonymes intérieure classes pour gérer tous les cas, vous avez juste besoin de remplacer un peu de l'Activité des méthodes pour gérer ces menu contextuel des événements.

Deuxièmement, il y a certainement des moyens plus faciles pour récupérer l'élément actuellement sélectionné. Tout ce que vous devez faire est de garder une référence à l' ListView ou à l' Adapter utilisé pour le remplir. Vous pouvez utiliser le ContextMenuInfo comme un AdapterContextMenuInfo pour obtenir la position de l'élément; et ensuite, vous pouvez soit utiliser ListView.getItemAtPosition() ou Adapter.getItem() pour récupérer l' Object spécifiquement lié à ce qui a été cliqué. Par exemple, à supposer que je suis à l'aide d' Activity.onCreateContextMenu(), je pourrais faire ceci:

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);

    // Get the info on which item was selected
    AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;

    // Get the Adapter behind your ListView (this assumes you're using
    // a ListActivity; if you're not, you'll have to store the Adapter yourself
    // in some way that can be accessed here.)
    Adapter adapter = getListAdapter();

    // Retrieve the item that was clicked on
    Object item = adapter.getItem(info.position);
}

@Override
public boolean onContextItemSelected(MenuItem item) {
    // Here's how you can get the correct item in onContextItemSelected()
    AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
    Object item = getListAdapter().getItem(info.position);
}

4voto

Ali Points 657

c’est un autre moyen de créer un menu contextuel ou de supprimer l’élément sélectionné.

      public class SimpleJokeList extends Activity {
public static final int Upload = Menu.FIRST + 1;
public static final int Delete = Menu.FIRST + 2;
int position;
ListView lv;
EditText jokeBox;
Button addJoke;
MyAdapter adapter;
private ArrayAdapter<String> mAdapter;
private ArrayList<String> mStrings = new ArrayList<String>();
String jokesToBeAdded;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.simplejokeui);



    lv=(ListView)findViewById(R.id.jokelist);
    addJoke=(Button)findViewById(R.id.addjoke);
    jokeBox=(EditText)findViewById(R.id.jokebox);


    mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mStrings);


    registerForContextMenu(lv);
    listItemClicked();
    addJokes();

private void addJokes() {
    // TODO Auto-generated method stub
    addJoke.setOnClickListener(new OnClickListener(){

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            jokesToBeAdded=jokeBox.getText().toString();
            if(jokesToBeAdded.equals("")){
            Toast.makeText(getApplicationContext(), "please enter some joke", Toast.LENGTH_LONG).show();
            }
            else{
                lv.setAdapter(mAdapter);
                mAdapter.add(jokesToBeAdded);
                jokeBox.setText(null);
            }   
        }
    });
}
private void listItemClicked() {
    // TODO Auto-generated method stub
    lv.setOnItemLongClickListener(new OnItemLongClickListener() {

        @Override
        public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
                int arg2, long arg3) {
            // TODO Auto-generated method stub
            position=arg2;
            return false;
        }
    });
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
        ContextMenuInfo menuInfo) {
    // TODO Auto-generated method stub
    super.onCreateContextMenu(menu, v, menuInfo);
    populateMenu(menu);
    menu.setHeaderTitle("Select what you wanna do");

}
private void populateMenu(ContextMenu menu) {
    // TODO Auto-generated method stub
     menu.add(Menu.NONE, Upload, Menu.NONE, "UPLOAD");
        menu.add(Menu.NONE, Delete, Menu.NONE, "DELETE");
}
 @Override
    public boolean onContextItemSelected(MenuItem item) 
    {
     return (applyMenuChoice(item) || super.onContextItemSelected(item));
    }


private boolean applyMenuChoice(MenuItem item) {
    // TODO Auto-generated method stub
    switch (item.getItemId()) 
    {   
         case Delete:

             String s=mAdapter.getItem(position);
             mAdapter.remove(s);
            // position--;
             Toast.makeText(getApplicationContext(),"Congrats u HAve Deleted IT", Toast.LENGTH_LONG).show();
        return (true);
    }
    return false;
}
 

3voto

sami boussacsou Points 249

et n'oubliez pas de mettre ceci

 registerForContextMenu(listview);
 

dans votre méthode onCreate pour que votre menu contextuel soit visible.

2voto

Patrick Kafka Points 4857

L'argument de vue ne correspond-il pas à la vue de la rangée sélectionnée ou la question me manque-t-elle?

 ListView lv;
private OnItemLongClickListener onLongClick = new OnItemLongClickListener() {
    public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
            int arg2, long arg3) {
        lv.showContextMenuForChild(arg1);
        lv.showContextMenu();
        return false;
    }
};
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X