Android 安卓:长按一下就可以在ListView中获得位置

Android 安卓:长按一下就可以在ListView中获得位置,android,listview,Android,Listview,所以,我知道在堆栈上有很多类似的问题;然而,他们没有一个人能够解决我的问题 我有一个用于显示用户名列表的ListActivity活动; 我创建了一个UserObj类来收集每个用户的信息,即UserObj实例(用户名、密码等) 现在,我成功地在我的列表视图中显示了用户名,并且在长时间单击特定用户名后,我还设法显示了一个浮动的上下文菜单,其中包含一些项目(删除,更改用户名,更改密码,更改电子邮件)。 下面我发布了我的ListActivitycode: public class ShowAccount

所以,我知道在堆栈上有很多类似的问题;然而,他们没有一个人能够解决我的问题

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

现在,我成功地在我的
列表视图中显示了用户名
,并且在长时间单击特定用户名后,我还设法显示了一个浮动的
上下文菜单
,其中包含一些项目(
删除
更改用户名
更改密码
更改电子邮件
)。 下面我发布了我的
ListActivity
code:

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

    }
}
}
问题是,当我选择一个菜单项(例如,与“删除”对应的菜单项)时,会显示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来查看单击每个菜单项时发生的情况没有发生崩溃

提前谢谢

编辑

经过一些诊断后,我发现传递给
onCreateContextMenu
menuInfo
为空。所以,我更接近问题的根源。
知道我为什么会得到一个空的
菜单信息吗?

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

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


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

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

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

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

  • 最好的方法是创建自定义适配器,然后在事件发生时在活动中实现自定义侦听器(onClick、onLongClick…)
  • 关于你的问题,我认为你在实施他的想法时错了。 请尝试我在应用程序中实施的解决方案: (在我的代码中,我使用了带有recycleview的自定义适配器,因此请尝试合并到您的代码中)

    • 类实现:
  • 公共类ListHistoryAdapter扩展了RecyclerView。适配器实现了View.OnCreateContextMenuListener{

    • 在BindViewHolder上的公共作废中方法:
    holder.itemView.setOnClickListener(新视图.OnClickListener(){
    @凌驾
    公共void onClick(视图v){
    //你的代码
    }
    });
    holder.itemView.setOnCreateContextMenuListener(此);
    holder.itemView.setTag(位置);

    • 适配器中的覆盖:
    @覆盖
    public void onCreateContextMenu(ContextMenu菜单,视图v,ContextMenu.ContextMenuInfo菜单信息){
    MenuItem deleteItem=menu.add(menu.NONE,1,1,“Delete”);
    final int pos=(int)v.getTag();
    deleteItem.setOnMenuItemClickListener(新的menuiItem.OnMenuItemClickListener(){
    @凌驾
    公共布尔onMenuItemClick(菜单项){
    //你的代码
    返回true;
    }
    });
    }

  • 最好的方法是创建自定义适配器,然后在事件发生时在活动中实现自定义侦听器(onClick、onLongClick…)
  • 关于你的问题,我认为你在实施他的想法时错了。 请尝试我在应用程序中实施的解决方案: (在我的代码中,我使用了带有recycleview的自定义适配器,因此请尝试合并到您的代码中)

    • 类实现:
  • 公共类ListHistoryAdapter扩展了RecyclerView。适配器实现了View.OnCreateContextMenuListener{

    • 在BindViewHolder上的公共作废中方法:
    holder.itemView.setOnClickListener(新视图.OnClickListener(){
    @凌驾
    公共void onClick(视图v){
    //你的代码
    }
    });
    holder.itemView.setOnCreateContextMenuListener(此);
    holder.itemView.setTag(位置);

    • 适配器中的覆盖:
    @覆盖
    public void onCreateContextMenu(ContextMenu菜单,视图v,ContextMenu.ContextMenuInfo菜单信息){
    MenuItem deleteItem=menu.add(menu.NONE,1,1,“Delete”);
    final int pos=(int)v.getTag();
    deleteItem.setOnMenuItemClickListener(新的menuiItem.OnMenuItemClickListener(){
    @凌驾
    公共布尔onMenuItemClick(菜单项){
    //你的代码
    返回true;
    }
    });
    }


    好的,我已经尝试过用这种方式注册视图,但没有成功…无论如何,非常感谢您提供的“setTag()“建议:)我将尝试它,希望绕过上一个问题。我也想问一下……是否有办法在
    onContextItemSelected
    中执行所需的操作,而不是
    onCreateContextMenu
    ?因为我需要的是将注意力限制在一个用户上,然后为该用户选择一个操作。以及所选的操作离子将在
    onContextItemSelected
    中可用,不是吗?@rabis我刚刚编辑了我的问题。我意识到我正在向
    onCreateContextMenu
    传递一个空的
    menuInfo
    。好的,两个都回答
     java.lang.NullPointerException: Attempt to read from field 'int android.widget.AdapterView$AdapterContextMenuInfo.position' on a null object reference