Android:在长期点击

时间:2017-03-02 18:42:58

标签: android listview

所以,我知道Stack上有很多类似的问题;然而,他们都没有设法解决我的问题。

我有一个ListActivity活动用于显示用户名列表; 我创建了一个UserObj类来收集有关每个用户的信息,即UserObj实例(用户名,密码等)。

现在我在ListView内成功显示了用户名,我还设法显示了包含一些项目的ContextMenuDelete,{{1} },ChangeUsername)长按特定用户名。 我在下面发布了ChangePassword代码:

ChangeEmail

然而,显然,我需要做的是实际触发执行所选用户的“删除用户”,“更改电子邮件”等任务;我认为需要相应的列表项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()然后我尝试检索该位置:

AdapterContextMenuInfo

问题是,当我选择一个菜单项(例如,对应于'delete'的菜单项)时,ANR对话框出现并报告以下异常:

onContextItemSelected

我能理解的是 int selectedId = info.position; 始终为空。但为什么? 我的代码中可能出现什么问题?

从上面的代码中可以看出,我试图通过打印测试字符串(例如 java.lang.NullPointerException: Attempt to read from field 'int android.widget.AdapterView$AdapterContextMenuInfo.position' on a null object reference )来查看单击每个菜单项时发生了什么,实际上如果我删除info.position没有崩溃发生...

提前致谢

修改

经过一些诊断后,我发现传递给"DELETE USER"的{​​{1}}为NULL。所以,我更接近问题的根源。 知道为什么我得到一个NULL int selectedId = info.position;

2 个答案:

答案 0 :(得分:1)

我遇到了类似的问题。我的解决方案是使用activity.registerForContextMenu(view)

在适配器内注册上下文菜单视图

可以在视图中将项目或甚至UserObj的位置设置为标记。

您可以在onCreateContextMenu()电话中获取该标记,并可以调用相应的操作。

答案 1 :(得分:1)

  1. 以最好的方式,您应该创建自定义适配器,然后在事件发生时在活动中实现自定义侦听器(onClick,onLongClick ...)
  2. 关于你的问题,我认为在实施@rabhis想法时你错了。 试试我在我的应用中实现的解决方案: (在我的代码中,我使用自定义适配器和recycleview,所以尝试合并到你的代码中)

    • 班级实施:
  3.   

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

    • public void 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; } }); }