English 中文(简体)
检测在ListView中选择的项目生成了上下文菜单(Android)
原标题:Detecting which selected item (in a ListView) spawned the ContextMenu (Android)

我有一个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;
  }
 });

但是我觉得那种方式非常笨拙。有没有其他更好的解决方案?

最佳回答

我就是这样做的。在我的onCreateContextMenu(...)方法中,我将ContextMenu.ContextMenuInfo转换为AdapterView.AdapterContextMenuInfo。从那里,您可以获取目标视图,再次将其强制转换为小部件。完整的代码在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);
}

请注意,我将所选文本和选择 ID 存储为私有字段。由于 UI 是线程限制的,我知道所选单词和所选单词 ID 字段将在以后的操作中是正确的。

问题回答

首先,我想知道你是否使用View.setOnCreateContextMenuListener()使事情变得过于复杂了。如果你使用Activity.registerForContextMenu(),事情就会变得简单得多,因为你可以使用Activity.onCreateContextMenu()Activity.onContextItemSelected()处理所有的菜单事件。这基本上意味着你不需要定义所有这些匿名内部类来处理每个事件;你只需要覆盖一些 Activity 方法来处理这些上下文菜单事件。

其次,有更简单的方法来检索当前选定的项。您只需要保留一个引用到ListView或用于填充它的Adapter。您可以使用AdapterContextMenuInfo作为ContextMenuInfo来获取项目的位置;然后,您可以使用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);
}

这是另一种创建上下文菜单和删除所选项目的方法。以下是整个代码。

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

不要忘记这样做。

registerForContextMenu(listview);

在你的onCreate方法中获取上下文菜单可见。

我们已经成功使用过:

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

难道不认为实际选择的浏览量,还是我在此没有问题?

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;
    }
};
@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 + "
" + text2 + "
" + text3;
    selectedWordId = info.id;
    menu.setHeaderTitle(selectedWord);
    MenuInflater inflater = this.getActivity().getMenuInflater();
    inflater.inflate(R.menu.list_menu, menu);
}

如果你在使用SimpleCursorAdapter,你可以这样做:

    @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

}




相关问题
Android - ListView fling gesture triggers context menu

I m relatively new to Android development. I m developing an app with a ListView. I ve followed the info in #1338475 and have my app recognizing the fling gesture, but after the gesture is complete, ...

AsyncTask and error handling on Android

I m converting my code from using Handler to AsyncTask. The latter is great at what it does - asynchronous updates and handling of results in the main UI thread. What s unclear to me is how to handle ...

Android intent filter for a particular file extension?

I want to be able to download a file with a particular extension from the net, and have it passed to my application to deal with it, but I haven t been able to figure out the intent filter. The ...

Android & Web: What is the equivalent style for the web?

I am quite impressed by the workflow I follow when developing Android applications: Define a layout in an xml file and then write all the code in a code-behind style. Is there an equivalent style for ...

TiledLayer equivalent in Android [duplicate]

To draw landscapes, backgrounds with patterns etc, we used TiledLayer in J2ME. Is there an android counterpart for that. Does android provide an option to set such tiled patterns in the layout XML?

Using Repo with Msysgit

When following the Android Open Source Project instructions on installing repo for use with Git, after running the repo init command, I run into this error: /c/Users/Andrew Rabon/bin/repo: line ...

Android "single top" launch mode and onNewIntent method

I read in the Android documentation that by setting my Activity s launchMode property to singleTop OR by adding the FLAG_ACTIVITY_SINGLE_TOP flag to my Intent, that calling startActivity(intent) would ...

From Web Development to Android Development

I have pretty good skills in PHP , Mysql and Javascript for a junior developer. If I wanted to try my hand as Android Development do you think I might find it tough ? Also what new languages would I ...

热门标签