当我单击特定视图时,如何获取列表视图中项目的位置?
正如标题所示,当我单击项目内部的视图时,我想知道该项目的确切位置。
假设我在 ArrayAdapter 的 getView() 方法中有以下代码:
...
holder = new ViewHolder ();
holder.iconAction = (ImageView)convertView.findViewById (R.id.download_item_iconAction);
holder.iconAction.setOnClickListener (new View.OnClickListener(){
@Override
public void onClick (View v){
//Item X is clicked
}
});
...
在 onClick() 中,我知道被单击的视图 v,但我不知道项目的位置。
让我们来玩一玩吧。当 getView() 创建视图时,我将在 ViewHolder 中保存位置:
public View getView (int position, View convertView, ViewGroup parent){
ViewHolder holder;
if (convertView == null){
holder = new ViewHolder ();
holder.iconAction = (ImageView)convertView.findViewById (id);
holder.iconAction.setOnClickListener (new View.OnClickListener(){
@Override
public void onClick (View v){
int pos = (Integer)v.getTag ();
}
});
holder.iconWait.setTag (position);
...
}else{
holder = (ViewHolder)convertView.getTag ();
}
...
}
此代码有效......但并非总是如此。如果您必须滚动列表才能查看所有项目,则视图将被回收。假设列表有 10 个元素,并且只有 5 个元素可见(可见意味着:如果我们看到某个项目的 1 个像素行,则该项目是可见的)。现在,如果我们向下滚动,我们将看到第六个元素,但第一个 (0) 仍然可见。我们再滚动一点,第一个元素将被隐藏,我们将看到第七个元素出现,但是这个新元素的视图是第一个元素 (0) 的视图。
所以我正在保存位置:0、1、2、3、4 和 5。第七个元素 (6) 将保存位置 0:错误。
获取单击回调的另一种方法是使用 ListView 的 OnItemClickListener 侦听器:
listView = getListView ();
listView.setOnItemClickListener (new AdapterView.OnItemClickListener(){
@Override
public void onItemClick (AdapterView<?> parentView, View childView, int position, long id){
...
}
});
如果向下滚动,我会获得确切的位置,但通过这种方式,无论单击的子视图如何,我都会在单击该项目时收到回调。
谢谢。
As the title says I want to know the exact position of the item when I click on a view that is inside the item.
Suppose I have the following code within the getView() method from ArrayAdapter:
...
holder = new ViewHolder ();
holder.iconAction = (ImageView)convertView.findViewById (R.id.download_item_iconAction);
holder.iconAction.setOnClickListener (new View.OnClickListener(){
@Override
public void onClick (View v){
//Item X is clicked
}
});
...
Within onClick() I know the view that is clicked, v, but I don't know the position of the item.
Let's do a trick. I'm going to save the position in a ViewHolder when getView() creates the view:
public View getView (int position, View convertView, ViewGroup parent){
ViewHolder holder;
if (convertView == null){
holder = new ViewHolder ();
holder.iconAction = (ImageView)convertView.findViewById (id);
holder.iconAction.setOnClickListener (new View.OnClickListener(){
@Override
public void onClick (View v){
int pos = (Integer)v.getTag ();
}
});
holder.iconWait.setTag (position);
...
}else{
holder = (ViewHolder)convertView.getTag ();
}
...
}
This code works... but not always. If you have to scroll the list to see all the items the views are recycled. Suppose that the list has 10 elements and only 5 are visible (visible means: if we see 1 pixel line of an item, then this item is visible). Now, if we scroll down we will see the sixth element but the first (0) is still visible. We scroll a little more and the first element will be hidden and we will see that the seventh element appears, BUT the view of this new element is the view of the first element (0).
So I'm saving the positions: 0, 1, 2, 3, 4 and 5. The seventh element (6) will have saved the position 0: Wrong.
Another way to get a click callback is using the ListView's OnItemClickListener listener:
listView = getListView ();
listView.setOnItemClickListener (new AdapterView.OnItemClickListener(){
@Override
public void onItemClick (AdapterView<?> parentView, View childView, int position, long id){
...
}
});
If I scroll down I get the exact position, but with this way I receive callbacks when the item is clicked, no matter the clicked child view.
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
你已经很接近了,你需要做的就是在 if/else 子句后面设置标签。这是为了确保在回收视图以及从新创建视图时更新标记。
例如
You're very nearly there, all you need to do is set the tag after your if/else clause. This is to make sure the tag is updated when the view is recycled as well as when it is created from new.
e.g
本地匿名类可以引用final本地变量。
将position :
getView()
方法更改为最终的然后您可以在
OnClickListener
中引用位置:Local anonymous classes can reference final local variables.
Make
position
final by changing yourgetView()
method to read:and then you can reference position from within the
OnClickListener
:如果您将
holder.iconWait.setTag (position)
移到 if/then 语句之外,那么您的第二个答案(在元素上设置标签)会很好地工作 - 也就是说,您应该将标签设置为也回收了行,而不仅仅是新充气的行。Your second answer (setting a tag on an element) would work fine if you moved
holder.iconWait.setTag (position)
outside of the if/then statement -- that is, you should set the tag on recycled rows too, not just on newly-inflated ones.我还需要添加其他数据以传递给 onClick,它也可以使用字符串。
I also needed to add other data to pass to onClick and it worked with strings too.