2017-03-02 95 views
0

因此,我知道Stack上有很多類似的問題;然而,他們中沒有人設法解決我的問題。Android:在ListView中獲取位置長按

我有一個ListActivity活動顯示用戶名列表; 我創建了一個UserObj類來收集有關每個用戶的信息,即UserObj實例(用戶名,密碼等)。

現在我成功地顯示了用戶名我ListView內,我也成功地顯示一個浮動ContextMenu的部分項目(DeleteChangeUsernameChangePasswordChangeEmail)在長點擊一個特定的用戶名。 下面我發佈我ListActivity代碼:

public class ShowAccountList extends ListActivity { 
List<UserObj> Allusers = new ArrayList<>(); // this is required to retrieve users from a local database 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_show_account_list); 

    final ListView UserList = (ListView)findViewById(android.R.id.list); 
    UserList.setLongClickable(true); 

    /*For completeness: here I fetch users from DB*/ 
    DataBaseUserHelper dbusers = new DataBaseUserHelper(getApplicationContext()); 
    dbusers.CreateTables(); 
    Allusers = dbusers.getAllUsers(); 
    dbusers.closeDB(); 

    /*Let's build a 'username' list to display*/ 
    List<String> namelist = new ArrayList<String>(); 
    for(int i=0 ; i< Allusers.size() ; i++){ 
     String uname = Allusers.get(i).username; 
     namelist.add(uname); 
    } 

    final ArrayAdapter<String> nameadapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,namelist); 
    UserList.setAdapter(nameadapter); 

    registerForContextMenu(UserList); 

    UserList.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { 


     @Override 
     public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { 


      openContextMenu(parent); 

      /*This outputs the CORRECT position*/ 
      System.out.println("Position: " + position + ", id: " + id); 
      return true; 
     } 



    }); 



} 

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

    MenuInflater inflater = getMenuInflater(); 
    inflater.inflate(R.menu.user_context_menu, menu); 

} 

@Override 
public boolean onContextItemSelected(MenuItem item){ 
    AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); 

    int selectedId = info.position; // HERE the problem shows up 

    // switch statement for debugging purposes 
    switch (item.getItemId()){ 
     case R.id.DeleteUser: 

      System.out.println("DELETE USER"); 
      return true; 
     case R.id.ChangeName: 
      System.out.println("CHANGE USERNAME"); 
      return true; 
     case R.id.ChangeEmail: 
      System.out.println("CHANGE EMAIL"); 
      return true; 
     case R.id.ChangePassword: 
      System.out.println("CHANGE PASSWORD"); 
      return true; 
     default: 
      return super.onContextItemSelected(item); 

    } 
} 
} 

不過,我需要做的,很明顯,是真正觸發「刪除用戶」,「更改電子郵件」的執行,等等的任務選定的用戶;我認爲爲了解哪些用戶應該進行這些修改,將需要相應的列表項目position。 所以,在這個題目下大多數人的問題(以及相應的答案)的建議,我鑄造item.getMenuInfo()AdapterContextMenuInfoonContextItemSelected,然後我試圖檢索與位置:

int selectedId = info.position; 

的問題是當我選擇一個菜單項(例如,對應於「刪除」之一)的ANR對話框顯示了與下面的異常報道:

java.lang.NullPointerException: Attempt to read from field 'int android.widget.AdapterView$AdapterContextMenuInfo.position' on a null object reference 

什麼我可以理解的是,info.position總是空。但爲什麼? 我的代碼中有什麼問題?

正如你可以從上面的代碼中看到的,我想看看通過打印測試線單擊每個單獨的菜單項時發生了什麼(例如,"DELETE USER"),實際上如果我刪除int selectedId = info.position;沒有發生崩潰......

在此先感謝

編輯

一些診斷後,我想通了,傳遞到onCreateContextMenumenuInfo爲NULL。所以,我更接近問題的根源。 任何想法爲什麼我得到一個NULL menuInfo

回答

1

我面臨類似的問題。我的解決辦法是使用註冊activity.registerForContextMenu(view)

的項目,甚至UserObj的位置可以被設置爲在視圖標記在適配器內部視圖上下文菜單。

您可以在onCreateContextMenu()調用中獲取標記,並可以調用相應的操作。

+0

好吧,我已經試圖以這種方式註冊視圖,但它沒有工作......無論如何非常感謝你的'setTag()'建議:)我會嘗試它希望繞過前面的問題 – NotANumber

+0

我會喜歡也問這個......有沒有辦法在'onContextItemSelected'而不是'onCreateContextMenu'中執行所需的動作?因爲我需要的是將我的注意力限制在一個用戶身上,然後爲該用戶選擇一個動作。所選的動作將在'onContextItemSelected'中可用,不是嗎? – NotANumber

+0

@rabis我剛剛編輯了我的問題。我意識到我正在向'onCreateContextMenu'傳遞一個NULL'menuInfo'。 – NotANumber

1
  1. 的最佳途徑,你應該創建自定義適配器,然後實現自定義監聽器在活動時發生的事件(的onClick,onLongClick ...)
  2. 關於你的問題,我認爲你實現@rabhis的想法是錯誤的。 試試我的解決方案,我在我的應用程序已經實現了: (在我的代碼,我使用的自定義適配器recycleview,所以要儘量合併到你的代碼)

    • 類實現:

public class ListHistoryAdapter extends RecyclerView.Adapter<ListHistoryAdapter.HistoryViewHolder> implements View.OnCreateContextMenuListener {

  • 公共無效onBindViewHolder方法:

holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // your code } }); holder.itemView.setOnCreateContextMenuListener(this); holder.itemView.setTag(position);

  • 覆蓋適配器:

@Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { MenuItem deleteItem = menu.add(Menu.NONE, 1, 1, "Delete"); final int pos = (int) v.getTag(); deleteItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { // your code return true; } }); }

+0

好吧,這兩個答案幫助我一點點,這就是爲什麼我upvoted,但我的問題是完全不同的......我最終發現,我的錯誤是返回** true **在** onItemLongClick **。將其設置爲返回** false **足以解決問題。 – NotANumber