Определение выбранного элемента (в ListView) порождает ContextMenu (Android) - PullRequest
56 голосов
/ 23 февраля 2010

У меня есть ListView , который позволит пользователю долго нажимать на элемент, чтобы получить контекстное меню. Проблема в том, что ListItem они долго нажимали. Я пытался сделать это:

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

но он просто зависает, пока не появится ANR . Я подозреваю, что после создания меню ListItem больше не выбирается.

Похоже, вы могли бы отслеживать клики или длительные клики, а затем записывать нажатый элемент:

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

но мне кажется, что это в основном глупо. У кого-нибудь есть лучшие решения для этого?

Ответы [ 8 ]

75 голосов
/ 23 февраля 2010

Я делаю именно это. В моем методе onCreateContextMenu(...) я приводил ContextMenu.ContextMenuInfo к AdapterView.AdapterContextMenuInfo. Оттуда вы можете получить targetView, который вы снова приводите к виджету. Полный код доступен в HomeActivity.java , ищите метод 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);
}

Обратите внимание, что я храню выделенный текст, а также идентификатор выбора в личных полях. Поскольку пользовательский интерфейс ограничен потоком, я знаю, что поля selectedWord и selectedWordId будут правильными для последующих действий.

66 голосов
/ 24 февраля 2010

Прежде всего, мне интересно, не усложняете ли вы вещи с помощью View.setOnCreateContextMenuListener(). Все становится намного проще, если вы используете Activity.registerForContextMenu(), потому что тогда вы можете просто использовать Activity.onCreateContextMenu() и Activity.onContextItemSelected() для обработки всех событий вашего меню. Это в основном означает, что вам не нужно определять все эти анонимные внутренние классы для обработки каждого события; вам просто нужно переопределить несколько методов Activity для обработки этих событий контекстного меню.

Во-вторых, есть определенно более простые способы получить выбранный в данный момент элемент. Все, что вам нужно сделать, это сохранить ссылку либо на ListView, либо на Adapter, использованный для его заполнения. Вы можете использовать ContextMenuInfo как AdapterContextMenuInfo, чтобы получить позицию элемента; и затем вы можете использовать ListView.getItemAtPosition() или Adapter.getItem(), чтобы получить Object, конкретно связанный с тем, на что был нажат. Например, предположим, что я использую Activity.onCreateContextMenu(), я мог бы сделать это:

@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);
}
4 голосов
/ 10 августа 2011

это еще один способ как создать контекстное меню и как удалить выбранный здесь элемент, это весь код

     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;
}
3 голосов
/ 23 сентября 2010

И не забудьте поставить это

registerForContextMenu(listview);

в вашем onCreate методе, чтобы ваше контекстное меню стало видимым.

2 голосов
/ 23 февраля 2010

Мы с успехом использовали:

@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;
    }
2 голосов
/ 23 февраля 2010

Не является ли аргумент представления фактическим представлением выбранной строки, или я здесь пропускаю вопрос?

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;
    }
};
1 голос
/ 25 декабря 2013
@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);
}
0 голосов
/ 24 сентября 2015

Если вы используете SimpleCursorAdapder, вы можете сделать это следующим образом

    @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

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...