Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView decorator adding extra padding on refresh

Tags:

android

So, I'm facing a weird problem while implementing RecyclerView in my project. I have a custom decorator to implement a consistent top and bottom padding and a rather different value of padding in between elements. Whenever I tap on refresh, i.e. fetch data from back-end and populate RecyclerView again, the padding increases and it keeps on increasing on each refresh.

This is the correct way

When I hit refresh (causing AsyncTask to execute again), the space between items increase. And it keeps on increase with each refresh.

Padding between items increasing

I have a typical RecyclerView like this

<android.support.v7.widget.RecyclerView
    android:id="@+id/recyclerview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clickable="false"
    android:focusableInTouchMode="false">
</android.support.v7.widget.RecyclerView>

Populating content inside RecyclerView is CardView with the following layout:

<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/cv"
android:layout_marginLeft="9dp"
android:layout_marginRight="9dp"
>

    <RelativeLayout
        android:id="@+id/itemLinearTop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:paddingTop="17dp"
        android:paddingRight="10dp"
        android:paddingLeft="10dp">

        <TextView
            android:id="@+id/tv1"
            android:textColor="@color/logo_black"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium" />


        <TextView
            android:id="@+id/tv2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/tv1"
            android:textColor="@color/logo_black"
            android:layout_alignParentRight="true"
            android:textAppearance="?android:attr/textAppearanceMedium" />

        <!-- More elements -->
    </RelativeLayout>
</android.support.v7.widget.CardView>

I am initializing and populating RecyclerView like this:

// In PostExecute of AsyncTask
RecyclerView rv = (RecyclerView) rootView.findViewById(R.id.recyclerview);
RecycleViewAdapter adapter = new FuelPricesRecycleViewAdapter(data);
rv.setAdapter(adapter);
rv.addItemDecoration(new RecyclerViewItemDecoration(30, item_count - 1));

And this is what my RecyclerViewItemDecoration class looks like:

public class RecyclerViewItemDecoration extends RecyclerView.ItemDecoration {
    private int space = 0;
    private int item_count = 0;
    private int ADDITIONAL_PADDING = 20;

    public RecyclerViewItemDecoration(int space, int item_count) {
        this.space = space;
        this.item_count = item_count;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        if(parent.getChildPosition(view) != item_count)
             outRect.bottom = space;

         // Add top margin only for the first item to avoid double space between items
         if(parent.getChildPosition(view) == 0)
             outRect.top = space + ADDITIONAL_PADDING;
         if(parent.getChildPosition(view) == item_count)
             outRect.bottom = space + ADDITIONAL_PADDING;
     }
 }

Thank you for your help!

like image 414
Basit Avatar asked Jul 02 '15 14:07

Basit


3 Answers

This is happening because we are trying to add itemDecorator to the recycler view which already have itemDecorator added to it, check first if its already there then don't add again

if (0 == recyclerview.getItemDecorationCount()) {
recyclerview.addItemDecoration(new DividerItemDecoration(ContextCompat.getDrawable(getActivity(), R.drawable.divider)));
}

This 0 will be the number of itemDecorator we have in recycler view, most of the time it'll be 0.

like image 144
Pankaj kumar Avatar answered Oct 23 '22 17:10

Pankaj kumar


You have to remove the item decoration before reseting new data.

rv.removeItemDecoration(yourDecorator)

Let me know if it works!

like image 17
yugidroid Avatar answered Oct 23 '22 16:10

yugidroid


You are adding Decoration each time recyclerview is loaded.

Use one flag instead :

private boolean flagDecoration = false;

if(!flagDecoration)
{
    rv.addItemDecoration(new RecyclerViewItemDecoration(30, item_count - 1));
    flagDecoration = true;    
}
like image 14
N Kaushik Avatar answered Oct 23 '22 16:10

N Kaushik