orange01
orange01

Reputation: 1614

Android ListView Layouts get mixed up on scroll

I have some problems with my custom ArrayAdapter.

I have two different layouts which I apply to the list item depending on an object value. Every time I scroll some of the items change where R.layout.layout1 should be applied, use R.layout.layout2 or the other way.

I thought of some problems on caching the layouts in the XML file.

The Problem I can´t figure out why the layouts changes on scroll.

Here is my Java-Code:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder = null;
    if (convertView == null) {
        LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (this.items.get(position).getId() == this.id)
            convertView = layoutInflater.inflate(R.layout.layout1);
        else
            convertView = layoutInflater.inflate(R.layout.layout2);
        holder = new ViewHolder();
        holder.textView1 = (TextView) convertView.findViewById(R.id.textViewItem1);
        holder.textView2 = (TextView) convertView.findViewById(R.id.textViewItem2);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }
    holder.textView1.setText(this.items.get(position).getInfo1());
    holder.textView2.setText(this.items.get(position).getInfo2());
    return convertView;
}

public static class ViewHolder {
    public TextView textView1;
    public TextView textView2;
}

And here is the ListView XML part:

<ListView
        android:id="@+id/listViewMessages"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:divider="@null"
        android:dividerHeight="0dp"
        android:stackFromBottom="true"
        android:transcriptMode="normal" />

Upvotes: 2

Views: 1162

Answers (1)

Marco Batista
Marco Batista

Reputation: 1428

Your convertView is probably being reused, you have to check when it is different that null, if it is the correct layout and reinflate the correct one.

You can add the layout id to the ViewHolder and check if the convertView is different than null, then inflate the correct layout if the id is different than the one you want.

Something like this:

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    ViewHolder holder = null;
    if(convertView == null || ((ViewHolder)convertView.getTag()).id != this.items.get(position).getId())
    {
        LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if(this.items.get(position).getId() == this.id)
            convertView = layoutInflater.inflate(R.layout.layout1);
        else
            convertView = layoutInflater.inflate(R.layout.layout2);
        holder = new ViewHolder();
        holder.textView1 = (TextView) convertView.findViewById(R.id.textViewItem1);
        holder.textView2 = (TextView) convertView.findViewById(R.id.textViewItem2);
        holder.id = this.items.get(position).getId();
        convertView.setTag(holder);
    }
    else
    {
        holder = (ViewHolder) convertView.getTag();
    }
    holder.textView1.setText(this.items.get(position).getInfo1());
    holder.textView2.setText(this.items.get(position).getInfo2());
    return convertView;
}

public static class ViewHolder
{
    public int id; //Assuming your id is an int, if not, changed it to the correct type
    public TextView textView1;
    public TextView textView2;
}

Upvotes: 5

Related Questions