简体   繁体   中英

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.

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.

pay attention to this point please!

if your app need remove item for any reason and you want to see removed item process in recyclerview so setISRecyclable to false is not good ,check it! so for every body wants to add this to adapter except(those that dont want to recycle some item for any reason) i have message:

please consider this point that in your adapter in onBindViewHolder for cases that need kind of toggle stuff Every call to onBindViewHolder must include either a load() call or a clear() call.

for example if you check the Boolean or 0-1 for setting some part of your RecyclerView item layout to gone or visible you should consider both of them in your If-Statement Block.

for example in this question i cant see else block inside configureViewHolder2 and 1 so messed up items happen maybe.

tnx to read patient reader

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM