Search code examples
androidandroid-recyclerviewadaptervertical-scrolling

Recycler View Scrolling messed up


I am trying a heterogeneous Recycler view, following this tutorial. Heterogeneous Layouts All is working fine expect for the part where i scroll the Recycler view, the layouts aren't displayed properly. I have 2 layouts, one has text and other has images, on scrolling I am left with alot of blank space in the text section,giving a feel to the viewer that there was some image previously here. I have checked links online but nothing solved the issue.Your help is needed and appreciated.
Here is my code

ComplexRecyclerViewAdapter

public class ComplexRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Object> items;
private final int STATUS = 0, IMAGE_STATUS = 1;
public ComplexRecyclerViewAdapter(List<Object> items) {
    this.items = items;
}
@Override
public int getItemCount() {
    return this.items.size();
}
@Override
public int getItemViewType(int position) {
    if (items.get(position) instanceof ArrayFeedItem) {
        return STATUS;
    } else if (items.get(position) instanceof ArrayFeedItemWithImage) {
        return IMAGE_STATUS;
    }
    return -1;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {

    RecyclerView.ViewHolder viewHolder;
    LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());

    if (viewType == STATUS){
        View v1 = inflater.inflate(R.layout.layout_viewholder1, viewGroup, false);
        viewHolder = new ViewHolder1(v1);
    }
    else if(viewType ==IMAGE_STATUS){
        View v2 = inflater.inflate(R.layout.layout_viewholder2, viewGroup, false);
        viewHolder = new ViewHolder2(v2);
    }
    else
    viewHolder=null;
    return viewHolder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {

    if (viewHolder.getItemViewType() == STATUS )
    {
        ViewHolder1 vh1 = (ViewHolder1) viewHolder;
        configureViewHolder1(vh1, position);
        vh1.setIsRecyclable(false);
    }
    else
    {
        ViewHolder2 vh2 = (ViewHolder2) viewHolder;
        configureViewHolder2(vh2, position);
        vh2.setIsRecyclable(false);
    }
}
private void configureViewHolder1(ViewHolder1 vh1, int position) {
    ArrayFeedItem item = (ArrayFeedItem) items.get(position);
    if (item != null) {
        vh1.getHolderImage().setImageResource(item.img);
        vh1.getHolderText().setText(item.txtname);
        vh1.getStatusMsg().setText(item.StatusMsg);
        vh1.getTimestamp().setText(item.Timestamp);
        vh1.getUrl().setText(item.URL);
    }
}

private void configureViewHolder2(ViewHolder2 vh2, int position) {
    ArrayFeedItemWithImage item = (ArrayFeedItemWithImage) items.get(position);
    if (item != null) {
        vh2.getHolderImage().setImageResource(item.img);
        vh2.getHolderText().setText(item.txtname);
        vh2.getStatusMsg().setText(item.StatusMsg);
        vh2.getTimestamp().setText(item.Timestamp);
        vh2.getUrl().setText(item.URL);
        vh2.getFeedImage().setImageResource(item.feedImage1);
    }
}
}

This is how I am binding the adapter to the recycle view.

Home Activity

list=(RecyclerView) findViewById(R.id.list);
adapter =new ComplexRecyclerViewAdapter(items);
list.setNestedScrollingEnabled(false);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
list.setLayoutManager(mLayoutManager);
list.setItemAnimator(new DefaultItemAnimator());
list.setAdapter(adapter);

ViewHolder1

public class ViewHolder1 extends RecyclerView.ViewHolder {
private ImageView Image;
private TextView Text,Timestamp,StatusMsg,Url;
public ViewHolder1(View itemView) {
    super(itemView);
    Image=(ImageView) itemView.findViewById(R.id.img);
    Text=(TextView)itemView.findViewById(R.id.txt);
    Timestamp=(TextView)itemView.findViewById(R.id.timestamp);
    StatusMsg=(TextView)itemView.findViewById(R.id.txtStatusMsg);
    Url=(TextView)itemView.findViewById(R.id.txtUrl);

}
public ImageView getHolderImage() {
    return Image;
}

public void setHolderImage(ImageView image) {
    this.Image = image;
}
public TextView getHolderText() {
    return Text;
}

public void setHolderText(TextView text) {
    this.Text = text;
}
public TextView getTimestamp() {
    return Timestamp;
}

public void setTimestamp(TextView timestamp) {
    this.Timestamp = timestamp;
}
public TextView getStatusMsg() {
    return StatusMsg;
}

public void setStatusMsg(TextView statusmsg) {
    this.StatusMsg = statusmsg;
}
public TextView getUrl() {
    return Url;
}

public void setUrl(TextView url) {
    this.Url = url;
}

}

layout_viewholder1

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

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_marginLeft="@dimen/feed_item_margin"
    android:layout_marginRight="@dimen/feed_item_margin"
    android:layout_marginTop="@dimen/feed_item_margin"
    android:background="@drawable/bg_parent_rounded_corner"
    android:orientation="vertical"
    android:paddingBottom="@dimen/feed_item_padding_top_bottom"
    android:paddingTop="@dimen/feed_item_padding_top_bottom"
    android:id="@+id/layout1"
    >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:paddingLeft="@dimen/feed_item_padding_left_right"
        android:paddingRight="@dimen/feed_item_padding_left_right" >

        <ImageView
            android:id="@+id/img"
            android:layout_width="@dimen/feed_item_profile_pic"
            android:layout_height="@dimen/feed_item_profile_pic"
            android:scaleType="fitCenter" >
        </ImageView>

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingLeft="@dimen/feed_item_profile_info_padd" >

            <TextView
                android:id="@+id/txt"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:textSize="@dimen/feed_item_profile_name"
                android:textStyle="bold"
                android:textColor="@color/black"/>

            <TextView
                android:id="@+id/timestamp"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:textColor="@color/timestamp"
                android:textSize="@dimen/feed_item_timestamp"
                />
        </LinearLayout>
    </LinearLayout>

    <TextView
        android:id="@+id/txtStatusMsg"
        android:textColor="@color/black"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="5dp"
        android:paddingLeft="@dimen/feed_item_status_pad_left_right"
        android:paddingRight="@dimen/feed_item_status_pad_left_right"
        android:paddingTop="@dimen/feed_item_status_pad_top" />

    <TextView
        android:id="@+id/txtUrl"
        android:textColor="@color/black"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:linksClickable="true"
        android:paddingBottom="10dp"
        android:paddingLeft="@dimen/feed_item_status_pad_left_right"
        android:paddingRight="@dimen/feed_item_status_pad_left_right"
        android:textColorLink="@color/link" />
</LinearLayout>

</LinearLayout>

Thanks in advance.


Solution

  • I have faced this issue and realised that in my case I was toggling view visibility inside public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {}

    So what was happening is due to bad code on my part sometimes some of the views were getting completely hidden and hence were not getting removed or recylcled. This caused the randomness in the view. So if you have some code that changes the view visibility then remove that and test if the issue is still there.