Android Adapter 多个getView

发布于 2024-09-08 16:22:32 字数 283 浏览 6 评论 0原文

我已经阅读了多次调用 getView 的问题和所有答案。但是,我没有找到解决我的问题的方法。

我有一个列表,其中行有两种状态:已读或未读。好吧,我希望第一次看到的项目有不同的颜色,当我滚动列表时,它们将颜色更改为“已读状态”。

为了做到这一点,在我的适配器的 getView 方法中,我在绘制该项目的行时设置了一个字段 isRead 。但问题如下:由于 getView 方法被多次调用,该字段被标记为已读,并且当列表显示在屏幕上时,它看起来好像已经被读取了。

有办法解决这个问题吗?

谢谢

i have read about the issue of getView called multiple times and all the answers. However, i don't find a solution for my problem.

I have a list where rows have two states: read or not. Well, i want to the items seen for first time have a different color and when i scroll the list, they change their color to "read state".

In order to do this, in the method getView of my adapter i set a field isRead when the row for that item is painted. But the problem is the following: since the method getView is called multiple times the field is marked as read and when the list is shown in the screen it appears as if it had already been read.

Any idea to fix this problem?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(4

软的没边 2024-09-15 16:22:32

我假设您指的是 getView 多次请求同一视图的问题。

ListView 这样做是因为它需要出于不同原因(滚动条大小、布局等)获取视图的测量值。

通常可以通过不在列表视图上使用“wrap_content”属性来避免此问题。

除此之外,使用 getView 来确定视图是否已显示是一个坏主意。 ListView 有许多优化,这些优化扰乱了每行调用 getView 的顺序,因此无法知道会发生什么,并且您的应用程序将开始显示奇怪的行为。

除了视图作为数据显示的概念之外,尽量避免视图和数据之间存在任何关系。

相反,让列表活动中的一些工作线程或事件侦听器监视列表中已向用户显示的项目、更新数据并在适配器上调用 dataSetChanged。

I assume you mean the issue of getView requesting the same view several times.

ListView does this because it needs to get measurements for the views for different reasons (scrollbar size, layout, etc)

This issue can usually be avoided by not using the "wrap_content" property on your listview.

Other than that, using getView to determine if a view has been displayed is simply a bad idea. ListView has many optimizations that mess with the order getView is called on for each row, so there is no way to know what will happen and your app will start showing odd behavior.

Try to avoid any relationship between the view and the data other than the concept of view as a display of that data.

Instead, have some worker thread or event listener in your listactivity watch the list for which items in the list have been displayed to the user, update the data, and call dataSetChanged on your adaptor.

凑诗 2024-09-15 16:22:32

我遇到了同样的问题,并且我在布局属性中根本没有引用“wrap_content”。尽管这是一个旧线程,但我无法弄清楚如何解决该问题。因此,我通过在适配器中添加一个列表来缓解它,该列表保存已绘制的位置,如下面的代码所示。我认为这不是立即这样做的方法,但它对我有用。

public class ImageAdapter extends BaseAdapter {
    private Context mContext;
    private List<Integer> usedPositions  = new ArrayList<Integer>();

    public ImageAdapter(Context c, List<String> imageUrls) {
        mContext = c;
        ...
    }

    ...

    // create a new ImageView for each item referenced by the Adapter
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView;
        if (convertView == null) { 
            imageView = new ImageView(mContext);
            imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            imageView.setPadding(8, 8, 8, 8);
        } else {
            imageView = (ImageView) convertView;
        }

        if (!usedPositions.contains(position)) {
            // Your code to fill the imageView object content
            usedPositions.add(position); // holds the used position
        }

        return imageView;
    }
}

I had the same problem and I had no reference at all to "wrap_content" in the layouts attirbute. Although this is an old thread I couldn't figured it out how to solve the issue. Thus, I mitigated it by adding a List in the Adapter that holds the positions already drawn, as shown in the code below. I think that it is not the right away of doing that, but it worked for me.

public class ImageAdapter extends BaseAdapter {
    private Context mContext;
    private List<Integer> usedPositions  = new ArrayList<Integer>();

    public ImageAdapter(Context c, List<String> imageUrls) {
        mContext = c;
        ...
    }

    ...

    // create a new ImageView for each item referenced by the Adapter
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView;
        if (convertView == null) { 
            imageView = new ImageView(mContext);
            imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            imageView.setPadding(8, 8, 8, 8);
        } else {
            imageView = (ImageView) convertView;
        }

        if (!usedPositions.contains(position)) {
            // Your code to fill the imageView object content
            usedPositions.add(position); // holds the used position
        }

        return imageView;
    }
}
女皇必胜 2024-09-15 16:22:32

不是你想要的工作方式。多次调用 getView() 的原因是允许操作系统测量行,以便知道如何布局它们。当他们单击它或选中某个框或其他内容时,您需要将其标记为已读。

Not the way you want it to work. The reason that getView() is called multiple times is to allow the OS to measure the rows so it knows how to lay them out. You would need to have it marked as read when they click it or check a box or something.

趁微风不噪 2024-09-15 16:22:32

当您不知道此代码块下面的任何内容都会扭曲布局时,这是避免双重调用的非常简单的方法。

private static List<String> usedPositions  = new ArrayList<String>();

……

@Override
public View getView(int position, View rowView, ViewGroup parent) {
    rowView = inflater.inflate(R.layout.download_listview_item, null);

    Log.d(LOG_TAG, "--> Position: " + position);

    if (!usedPositions.contains(String.valueOf(position))){
        usedPositions.add(String.valueOf(position));
        return rowView;
    }else{
        usedPositions.remove(String.valueOf(position));
    }

Here is a very simple way of avoiding the double call when you know nothing below this block of code will distort the layout.

private static List<String> usedPositions  = new ArrayList<String>();

...

@Override
public View getView(int position, View rowView, ViewGroup parent) {
    rowView = inflater.inflate(R.layout.download_listview_item, null);

    Log.d(LOG_TAG, "--> Position: " + position);

    if (!usedPositions.contains(String.valueOf(position))){
        usedPositions.add(String.valueOf(position));
        return rowView;
    }else{
        usedPositions.remove(String.valueOf(position));
    }

...

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