当我单击特定视图时,如何获取列表视图中项目的位置?

发布于 10-20 12:10 字数 1751 浏览 5 评论 0原文

正如标题所示,当我单击项目内部的视图时,我想知道该项目的确切位置。

假设我在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

墨落画卷 2024-10-27 12:10:49

你已经很接近了,你需要做的就是在 if/else 子句后面设置标签。这是为了确保在回收视图以及从新创建视图时更新标记。

例如

    if (convertView == null){
        holder = new ViewHolder ();
        ...
    }else{
        holder = (ViewHolder)convertView.getTag ();
    }
 holder.iconWait.setTag (position);

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

    if (convertView == null){
        holder = new ViewHolder ();
        ...
    }else{
        holder = (ViewHolder)convertView.getTag ();
    }
 holder.iconWait.setTag (position);
飘过的浮云 2024-10-27 12:10:49

本地匿名类可以引用final本地变量。

getView() 方法更改为最终的position :

public View getView (final int position, View convertView, ViewGroup parent) {

然后您可以在 OnClickListener 中引用位置:

holder.iconAction.setOnClickListener (new View.OnClickListener(){
    @Override
    public void onClick (View v){
        ... use position here ...
    }
});

Local anonymous classes can reference final local variables.

Make position final by changing your getView() method to read:

public View getView (final int position, View convertView, ViewGroup parent) {

and then you can reference position from within the OnClickListener:

holder.iconAction.setOnClickListener (new View.OnClickListener(){
    @Override
    public void onClick (View v){
        ... use position here ...
    }
});
赠我空喜 2024-10-27 12:10:49

如果您将 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.

梦情居士 2024-10-27 12:10:49

我还需要添加其他数据以传递给 onClick,它也可以使用字符串。

holder.iconWait.setTag ("String data here");

I also needed to add other data to pass to onClick and it worked with strings too.

holder.iconWait.setTag ("String data here");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文