2010-02-23 19 views
55

我有一個ListView,它允許用戶長按一個項目來獲取上下文菜單。我遇到的問題是確定他們長期按下哪個ListItem。我試着這樣做:檢測哪個選定的項目(在ListView中)產生了ContextMenu(Android)

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

但感覺majorly kludgey給我。有沒有人有更好的解決方案?

回答

75

我做的正是這一點。在我的onCreateContextMenu(...)方法中,我投了ContextMenu.ContextMenuInfoAdapterView.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); 
} 

請注意,我將所選文本以及選擇標識存儲在專用字段中。由於UI是線程受限的,因此我知道selectedWord和selectedWordId字段對於以後的操作是正確的。

+0

我也是這樣做的。關鍵是弄清楚ContextMenuInfo對象是AdapterContextMenuInfo的一個實例。花了我一段時間來弄清楚。 – 2010-02-23 20:46:26

+6

只有當物品背後的實際數據與從適配器創建的視圖緊密相關時,這纔會起作用。我發現這通常不是我創建的更復雜的適配器的情況(例如,它會顯示圖像和名稱;點擊它可以打開有關該項目的更多詳細信息,這取決於存儲在適配器)。 – 2010-02-23 21:54:45

+0

優秀的回覆。同上找出ContextMenuInfo對象是AdapterContextMenuInfo的一個實例。 – pilcrowpipe 2012-04-22 20:15:54

2

是不是視圖參數實際選定的行視圖,或者我在這裏錯過了問題?

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

視圖參數是ListView。 – 2010-02-24 21:35:56

2

我們已經成功應用於:

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

首先,我想知道你是否因使用View.setOnCreateContextMenuListener()而使事情變得過於複雜。如果您使用Activity.registerForContextMenu(),事情會變得更容易,因爲您可以使用Activity.onCreateContextMenu()Activity.onContextItemSelected()來處理所有菜單事件。它基本上意味着你不必定義所有這些匿名內部類來處理每個事件;你只需要重寫一些Activity方法來處理這些上下文菜單事件。

其次,肯定有更簡單的方法來檢索當前選擇的項目。所有你需要做的是保留一個參考ListViewAdapter用於填充它。您可以使用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); 
} 
+0

我有一個關於你的答案的問題 - 如何做到這一點,如果你有你的XML佈局文件中的列表視圖小部件?我認爲你不能覆蓋listactivity方法。那麼如何聽上下文菜單點擊呢?在此先感謝 – mad 2010-12-11 17:12:25

+3

我欠你一杯啤酒! – 2011-11-28 16:10:53

+7

這應該是被接受的答案。謝謝。 – 2012-06-01 18:16:38

3

而且不要忘了把這個

registerForContextMenu(listview); 

onCreate方法讓你的右鍵菜單中可見。

+0

如果使用適配器,請在「listview.setAdapter(適配器)」之前註冊。 – Kush 2014-06-15 13:15:53

+0

@sami我正在獲取信息null – PriyankaChauhan 2017-01-05 10:49:48

4

這是關於如何創建上下文菜單另一種方式作如何刪除此處選擇的項目是整個代碼

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

我使用的是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 

} 
相關問題