ListView:convertView / holder变得困惑

时间:2010-03-22 21:32:51

标签: android listview

我正在使用ListView,试图让convertView / referenceHolder优化正常工作,但它给了我麻烦。 (这是将R.id.xxx指针存储为每个View的标记以避免必须调用findViewById的系统)。我有一个ListView填充了ImageView的简单行和一些文本,但ImageView可以格式化为肖像大小的图像(高和窄)或横向大小的图像(短和宽)。它正在为每一行调整这种格式,这种格式不符合我的预期。

基本系统首先是它,它为每一行的布局膨胀,并根据数据设置ImageView的设置,并包含一个int,表示包含R.id.xxx值的标记中的方向。然后,当它开始重用convertView时,它会根据新行的方向检查此保存的方向。那么理论是如果方向相同,那么ImageView应该已经正确设置了。如果不是,则根据需要设置ImageView的参数并更新标记。

然而,我发现它在某种程度上变得困惑;有时标签会与ImageView的方向不同步。例如,标签仍会显示纵向,但实际的ImageView仍将采用横向布局。我无法找到这种情况发生的方式或时间;它与方向,列表中的位置或滚动速度不一致。我可以通过简单地删除有关convertView方向的检查来解决问题,并且只是总是设置ImageView的参数,但这似乎无法实现此优化的目的。

有人能看到我在下面的代码中做错了吗?

static LinearLayout.LayoutParams layoutParams;
(...)

public View getView(int position, View convertView, ViewGroup parent){
    ReferenceHolder holder;

    if (convertView == null){
        convertView = inflater.inflate(R.layout.pick_image_row, null);
        holder = new ReferenceHolder();
        holder.getIdsAndSetTag(convertView, position);
        if (data[position][ORIENTATION] == LANDSCAPE) {
            // Layout defaults to portrait settings, so ImageView size needs adjusting. 
            // layoutParams is modified here, with specific values for width, height, margins etc
            holder.image.setLayoutParams(layoutParams);
        }
        holder.orientation = data[position][ORIENTATION];

    } else {
        holder = (ReferenceHolder) convertView.getTag();
        if (holder.orientation != data[position][ORIENTATION]){  //This is the key if statement for my question
            switch (image[position][ORIENTATION]) {
            case PORTRAIT:
                // layoutParams is reset to the Portrait settings
                holder.orientation = data[position][ORIENTATION];
                break;

            case LANDSCAPE:
                // layoutParams is reset to the Landscape settings
                holder.orientation = data[position][ORIENTATION];
                break;
            }
            holder.image.setLayoutParams(layoutParams);
        }               
    }

    // and the row's image and text is set here, using holder.image.xxx
    // and holder.text.xxx

    return convertView;
}

static class ReferenceHolder {
    ImageView image;
    TextView text;
    int orientation;

    void getIdsAndSetTag(View v, int position){
        image = (ImageView) v.findViewById(R.id.pickImageImage);
        text = (TextView) v.findViewById(R.id.pickImageText);
        orientation = data[position][ORIENTATION];
        v.setTag(this);
    }
}

谢谢!

1 个答案:

答案 0 :(得分:2)

不是将方向作为ReferenceHolder的数据成员,而是检查LayoutParams的实际ImageView,看看它的方向。这样,根据定义,你可以'以某种方式失去同步。

老实说,我对你所拥有的代码感到困惑,因为你似乎永远不会改变layoutParams,这似乎有点重要。或者,您不应该layoutParamsPortraitlayoutParamsLandscape或其他什么?对我来说,看起来规则是:

  • 如果是肖像并且最初创建了该行,请将其保留为肖像
  • 其他所有内容都是风景,无论orientation标志是什么,因为您始终将其设置为layoutParams,这可能是风景