J'ai un ListView qui permettra à l'utilisateur d'appuyer longuement sur un élément pour obtenir un menu contextuel. Le problème que je rencontre est de déterminer quelle ListItem
ils pressent depuis longtemps. J'ai essayé de faire ça:
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'un ANR apparaisse. Je soupçonne qu'après la création du menu, la ListItem
n'est plus sélectionnée.
Il semble que vous puissiez surveiller les clics ou les clics longs, puis enregistrer l'élément sur lequel vous avez cliqué:
mArrivalsList.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override public boolean onItemLongClick(AdapterView<?> parent, View v, int position, long id) {
// record position/id/whatever here
return false;
}
});
mais cela me semble très compliqué. Quelqu'un at-il de meilleures solutions pour cela?
Je fais exactement cela. Dans ma méthode onCreateContextMenu(...)
, je convertis le ContextMenu.ContextMenuInfo
en AdapterView.AdapterContextMenuInfo
. À partir de là, vous pouvez obtenir le targetView, que vous rediffuserez dans le widget. Le code complet est disponible dans HomeActivity.Java , recherchez la méthode onCreateContextMenu(...)
.
@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 l'identifiant de sélection dans des champs privés. Étant donné que l’interface utilisateur est confinée à un thread, je sais que les champs selectedWord et selectedWordId seront corrects pour les actions ultérieures.
Tout d’abord, je me demandais si vous compliquiez un peu les choses en utilisant View.setOnCreateContextMenuListener()
. Les choses deviennent beaucoup plus faciles si vous utilisez Activity.registerForContextMenu()
, car vous pouvez simplement utiliser Activity.onCreateContextMenu()
et Activity.onContextItemSelected()
pour gérer tous vos événements de menu. Cela signifie fondamentalement que vous n'avez pas à définir toutes ces classes internes anonymes pour gérer chaque événement; il vous suffit de remplacer quelques méthodes Activity pour gérer ces événements de menu contextuel.
Deuxièmement, il existe des moyens nettement plus simples de récupérer l'élément actuellement sélectionné. Tout ce que vous avez à faire est de conserver une référence à la variable ListView
ou à la variable Adapter
utilisée pour la remplir. Vous pouvez utiliser ContextMenuInfo en tant que AdapterContextMenuInfo pour obtenir la position de l'élément. et vous pouvez alors utiliser ListView.getItemAtPosition()
ou Adapter.getItem()
pour récupérer le Object
spécifiquement lié à ce qui a été cliqué. Par exemple, en utilisant 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);
}
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;
}
Et n'oubliez pas de mettre ceci
registerForContextMenu(listview);
dans votre méthode onCreate
pour que votre menu contextuel soit visible.
L'argument de vue n'est-il pas la vue de la rangée réellement 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;
}
};
Nous avons utilisé avec succès:
@Override
public boolean onContextItemSelected
(
MenuItem item
)
{
if (!AdapterView.AdapterContextMenuInfo.class.isInstance (item.getMenuInfo ()))
return false;
AdapterView.AdapterContextMenuInfo cmi =
(AdapterView.AdapterContextMenuInfo) item.getMenuInfo ();
Object o = getListView ().getItemAtPosition (cmi.position);
return true;
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
View TargetV=(View) info.targetView;
text1 = (String) ((TextView) TargetV.findViewById(R.id.textView1)).getText();
text2 = (String) ((TextView) TargetV.findViewById(R.id.textView2)).getText();
if(List3Ok){
text3 = (String) ((TextView) TargetV.findViewById(R.id.textView3)).getText();
}
selectedWord = text1 + "\n" + text2 + "\n" + text3;
selectedWordId = info.id;
menu.setHeaderTitle(selectedWord);
MenuInflater inflater = this.getActivity().getMenuInflater();
inflater.inflate(R.menu.list_menu, menu);
}
Si vous utilisez SimpleCursorAdapder
, vous pouvez le faire comme ceci
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
getActivity().getMenuInflater().inflate(R.menu.project_list_item_context, menu);
// Getting long-pressed item position
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
int position = info.position;
// Get all records from adapter
Cursor c = ((SimpleCursorAdapter)getListAdapter()).getCursor();
// Go to required position
c.moveToPosition(position);
// Read database fields values associated with our long-pressed item
Log.d(TAG, "Long-pressed-item with position: " + c.getPosition());
Log.d(TAG, "Long-pressed-item _id: " + c.getString(0));
Log.d(TAG, "Long-pressed-item Name: " + c.getString(1));
Log.d(TAG, "Long-pressed-item Date: " + c.getString(2));
Log.d(TAG, "Long-pressed-item Path: " + c.getString(3));
// Do whatever you need here with received values
}