David Gordon
David Gordon

Reputation: 287

RecyclerView onBindViewHolder position not as expected

I know this problem has being asked numerous times relating to ListViews, However I have never been able to understand the solution truly. I am aware that the position parameter of onBindViewHolder() in RecyclerViewAdapter is similar to the position parameter in listAdapter getView(). I also am aware that the position is only relative to visible views. So how can I go about loading an Image for each row of the RecyclerView? The image may be different depending on position. The RecyclerView has a known number of rows (57)

I intend to have an array list of 'favourites'for example int[] fav = {2,6,30,40}. So if position equals one of these elements then ImageView sets one drawble, else it sets another.Could anyone help me with this?

At the moment position repeats itself and many extra rows are setting the drawable reserved for row IDs in the fav array

Thank You,

public class RecyclerViewAdapter extends ...... {

private List<StockItemRow> stockItems;
private Context mContext;
private int[] favourites = {2,3};



RecyclerViewAdapter(Context context, List modelData) {
    if (modelData == null) {
        throw new IllegalArgumentException("modelData must not be null");
    }
    this.stockItems = modelData;
    this.mContext = context;
}


@Override
public ListItemViewHolder onCreateViewHolder(...)
{
    View itemView =     
    LayoutInflater.fromLayoutInflater.
    from(viewGroup.getContext()).
    inflate(R.layout.listitem_row, viewGroup, false);

    return new ListItemViewHolder(itemView);
}


@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onBindViewHolder(ListItemViewHolder viewHolder, int position) {
    StockItemRow stockModel = stockItems.get(position);

    for(int i = 0;i<favourites.length;i++) {
        if (position == favourites[i]) {
             viewHolder.star.setImageResource(R.drawable.star_pressed);

    }
 }

 @Override
 public int getItemCount() {
     return stockItems.size();
 }

public final static class ListItemViewHolder extends....  
   ImageView star;

   public ListItemViewHolder(final View itemView) {
        super(itemView);
        star= (ImageView) itemView.findViewById(R.id.star);
   }
}
}

XML

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">

<android.support.v7.widget.RecyclerView
    android:layout_height="match_parent"
    android:id="@+id/recyclerView"
    android:divider="@drawable/list_selector"

    android:dividerHeight="1dip"
    android:layout_width="match_parent">
</android.support.v7.widget.RecyclerView>


</LinearLayout>

Upvotes: 4

Views: 6678

Answers (1)

Larry Schiefer
Larry Schiefer

Reputation: 15775

@Deev is correct: the position is the position within the adapter, not on screen. The problem you are running into is because your onBindViewHolder() method is only handling the favorite case, but not the non-favorite case. The ViewHolder pattern is used for efficiency and it's re-using views. Change the code to be this:

int fav_res = R.drawable.star;
for(int i = 0;i<favourites.length;i++) {
    if (position == favourites[i]) {
        fav_res = R.drawable.star_presed;
        break;
    }
}

viewHolder.star.setImageResource(fav_res);

Upvotes: 3

Related Questions