2017-03-02 65 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