DarkMalice
DarkMalice

Reputation: 205

Imageview not displaying correctly through listview adapter

In my adapter I have three variations of view using yellow, orange and red for their different text-color. To go along with these, I'm trying to have three different images as thumbnails (hhy, hho, hhr). When it runs the images do not match with their corresponding view item, I'm getting the hho and hhy either one item too early or late in the listview. I have the imageview layout names correct so I'm unsure why they are not displaying correctly.

PostItemAdapter.java

@Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        ViewHolder viewHolder;
        int listViewItemType = getItemViewType(position);

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.postitem, null);

            viewHolder = new ViewHolder();
            //viewHolder.itemThumbView = (ImageView) convertView.findViewById(R.id.itemThumb);

            if (listViewItemType == TYPE_short) {
                viewHolder.itemTitleView = (TextView) convertView.findViewById(R.id.itemTitleLabel);
                viewHolder.itemThumbView = (ImageView) convertView.findViewById(R.id.itemThumb);
            } else if (listViewItemType == TYPE_med) {
                viewHolder.itemTitleView = (TextView) convertView.findViewById(R.id.itemTitleLabel1);
                viewHolder.itemThumbView = (ImageView) convertView.findViewById(R.id.itemThumb1);
            } else {
                viewHolder.itemTitleView = (TextView) convertView.findViewById(R.id.itemTitleLabel2);
                viewHolder.itemThumbView = (ImageView) convertView.findViewById(R.id.itemThumb2);
            }
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        if (listViewItemType == TYPE_short) {
            viewHolder.itemTitleView.setText(datas.get(position).itemTitle);
            viewHolder.itemThumbView.setImageResource(R.drawable.hhy);
        } else if (listViewItemType == TYPE_med) {
            viewHolder.itemTitleView.setText(datas.get(position).itemTitle);
            viewHolder.itemThumbView.setImageResource(R.drawable.hho);
        } else {
            viewHolder.itemTitleView.setText(datas.get(position).itemTitle);
            viewHolder.itemThumbView.setImageResource(R.drawable.hhr);
        }

        return convertView;
    }
}

and the relevant layout postitem.xml

 <ImageView
        android:id="@+id/itemThumb"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:src="@drawable/hhy"
        android:scaleType="centerCrop"
        android:layout_marginRight="5dp"/>

    <ImageView
        android:id="@+id/itemThumb1"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:src="@drawable/hho"
        android:scaleType="centerCrop"
        android:layout_marginRight="5dp"/>

    <ImageView
        android:id="@+id/itemThumb2"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:src="@drawable/hhr"
        android:scaleType="centerCrop"
        android:layout_marginRight="5dp"/>

    <TextView
        android:id="@+id/itemTitleLabel"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignTop="@id/itemThumb"
        android:layout_toRightOf="@id/itemThumb"
        android:maxLines="2"
        android:textIsSelectable="false"
        android:textSize="16sp"
        android:textStyle="bold"
        android:textColor="#ffff00"
        android:ellipsize="end"
        />

    <TextView
        android:id="@+id/itemTitleLabel1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignTop="@id/itemThumb"
        android:layout_toRightOf="@id/itemThumb"
        android:maxLines="2"
        android:textIsSelectable="false"
        android:textSize="16sp"
        android:textStyle="bold"
        android:textColor="#ffa500"
        android:ellipsize="end"
         />

    <TextView
        android:id="@+id/itemTitleLabel2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignTop="@id/itemThumb"
        android:layout_toRightOf="@id/itemThumb"
        android:maxLines="2"
        android:textIsSelectable="false"
        android:textSize="16sp"
        android:textStyle="bold"
        android:textColor="#ff0000"
        android:ellipsize="end"
         />

Image of what's happening; enter image description here

Upvotes: 0

Views: 720

Answers (2)

honeal
honeal

Reputation: 1599

There's a few issues with what you have going on in your question. Recycled views are intended to only be inflated/created enough times to populate the visible portion of your ListView fully for the first time. They are then recycled as you scroll rather than created again.

Which means this block is only called the first few times:

if (convertView == null) {
        convertView = inflater.inflate(R.layout.postitem, null);

        viewHolder = new ViewHolder();
        //viewHolder.itemThumbView = (ImageView) convertView.findViewById(R.id.itemThumb);

        if (listViewItemType == TYPE_short) {
            viewHolder.itemTitleView = (TextView) convertView.findViewById(R.id.itemTitleLabel);
            viewHolder.itemThumbView = (ImageView) convertView.findViewById(R.id.itemThumb);
        } else if (listViewItemType == TYPE_med) {
            viewHolder.itemTitleView = (TextView) convertView.findViewById(R.id.itemTitleLabel1);
            viewHolder.itemThumbView = (ImageView) convertView.findViewById(R.id.itemThumb1);
        } else {
            viewHolder.itemTitleView = (TextView) convertView.findViewById(R.id.itemTitleLabel2);
            viewHolder.itemThumbView = (ImageView) convertView.findViewById(R.id.itemThumb2);
        }
        convertView.setTag(viewHolder);
    }

For subsequent recycles your ViewHolder could be pointing at an unintended resource. If the current item is TYPE_med, the viewHolder.itemThumbView could have been created with a different resource reference (i.e. TYPE_short at the time of creation). Fixing this still won't solve your problem because you have the other two ImageViews/TextViews hanging around.

I'm not seeing any apparent need to have multiple ImageViews/TextViews so rather than setting visibility on everything the more accepted approach would be:

static class ViewHolder
{
    private TextView mTextViewTitle;
    private ImageView mImageViewThumb;
}

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    ViewHolder viewHolder;
    Item i = datas.get(position);
    int listViewItemType = i.viewtype;

    if (convertView == null) {
        convertView = inflater.inflate(R.layout.postitem, null);

        viewHolder = new ViewHolder();

        viewHolder.mTextViewTitle = (TextView) convertView.findViewById(R.id.itemTitleLabel);
        viewHolder.mImageViewThumb = (ImageView) convertView.findViewById(R.id.itemThumb);

        convertView.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) convertView.getTag();
    }

    viewHolder.mTextViewTitle.setText(i.itemTitle);

    if (listViewItemType == TYPE_short) {
        viewHolder.mTextViewTitle.setTextColor(Color.parseColor("#ffff00"));
        viewHolder.mImageViewThumb.setImageResource(R.drawable.hhy);
    } else if (listViewItemType == TYPE_med) {
        viewHolder.mTextViewTitle.setTextColor(Color.parseColor("#ffff00"));
        viewHolder.mImageViewThumb.setImageResource(R.drawable.hho);
    } else {
        viewHolder.mTextViewTitle.setTextColor(Color.parseColor("#ff0000"));
        viewHolder.mImageViewThumb.setImageResource(R.drawable.hhr);
    }

    return convertView;
}

It would be better to have your colors defined in resources, but I'll save that for another discussion.

Your new XML:

<ImageView
    android:id="@+id/itemThumb"
    android:layout_width="48dp"
    android:layout_height="48dp"
    android:scaleType="centerCrop"
    android:layout_marginRight="5dp" />

<TextView
    android:id="@+id/itemTitleLabel"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_alignTop="@id/itemThumb"
    android:layout_toRightOf="@id/itemThumb"
    android:maxLines="2"
    android:textIsSelectable="false"
    android:textSize="16sp"
    android:textStyle="bold"
    android:ellipsize="end" />

Upvotes: 4

DarkMalice
DarkMalice

Reputation: 205

Okay so, my problem is that when the listview views were being recycled they were overwriting, or unable to overwrite, the pre-existing image/text. My rather hacky solution was to use the following code. If anyone knows the way you are supposed to resolve this I would be interested in hearing about it :P

PostItemAdapter.java (ViewHolder)

 static class ViewHolder
    {
        private TextView itemTitleViewY, itemTitleViewO, itemTitleViewR;
        private ImageView itemThumbViewY, itemThumbViewO, itemThumbViewR;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        ViewHolder viewHolder;
        Item i = datas.get(position);
        int listViewItemType = i.viewtype;

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.postitem, null);

            viewHolder = new ViewHolder();

            viewHolder.itemTitleViewY = (TextView) convertView.findViewById(R.id.itemTitleLabel);
            viewHolder.itemThumbViewY = (ImageView) convertView.findViewById(R.id.itemThumb);
            viewHolder.itemTitleViewO = (TextView) convertView.findViewById(R.id.itemTitleLabel1);
            viewHolder.itemThumbViewO = (ImageView) convertView.findViewById(R.id.itemThumb1);
            viewHolder.itemTitleViewR = (TextView) convertView.findViewById(R.id.itemTitleLabel2);
            viewHolder.itemThumbViewR = (ImageView) convertView.findViewById(R.id.itemThumb2);

            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        switch (listViewItemType) {
            case 0:
                viewHolder.itemTitleViewY.setText(i.itemTitle);
                viewHolder.itemTitleViewO.setText("");
                viewHolder.itemTitleViewR.setText("");
                viewHolder.itemThumbViewY.setVisibility(View.VISIBLE);
                viewHolder.itemThumbViewO.setVisibility(View.INVISIBLE);
                viewHolder.itemThumbViewR.setVisibility(View.INVISIBLE);
                Log.d("DEBUG CHECKME", "getItemViewType Y: " + i.itemTitle + ", " + i.viewtype + ", " + i);
                break;
            case 1:
                viewHolder.itemTitleViewO.setText(i.itemTitle);
                viewHolder.itemTitleViewY.setText("");
                viewHolder.itemTitleViewR.setText("");
                viewHolder.itemThumbViewO.setVisibility(View.VISIBLE);
                viewHolder.itemThumbViewY.setVisibility(View.INVISIBLE);
                viewHolder.itemThumbViewR.setVisibility(View.INVISIBLE);
                Log.d("DEBUG CHECKME", "getItemViewType O: " + i.itemTitle + ", " + i.viewtype + ", " + i);
                break;
            case 2:
                viewHolder.itemTitleViewR.setText(i.itemTitle);
                viewHolder.itemTitleViewO.setText("");
                viewHolder.itemTitleViewY.setText("");
                viewHolder.itemThumbViewR.setVisibility(View.VISIBLE);
                viewHolder.itemThumbViewY.setVisibility(View.INVISIBLE);
                viewHolder.itemThumbViewO.setVisibility(View.INVISIBLE);
                Log.d("DEBUG CHECKME", "getItemViewType R: " + i.itemTitle + ", " + i.viewtype + ", " + i);
                break;
            default:
                viewHolder.itemTitleViewY.setText("");
                viewHolder.itemTitleViewO.setText("");
                viewHolder.itemTitleViewR.setText("");
                viewHolder.itemThumbViewY.setVisibility(View.INVISIBLE);
                viewHolder.itemThumbViewO.setVisibility(View.INVISIBLE);
                viewHolder.itemThumbViewR.setVisibility(View.INVISIBLE);
                Log.d("DEBUG CHECKME", "getItemViewType D: " + i.itemTitle + ", " + i.viewtype + ", " + i);
                break;
        }
        return convertView;
    }

Upvotes: 0

Related Questions