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