RecyclerView creating margins between items

11,487

Solution 1

Have you tried ItemDecoration with your RecyclerView ? That's usefull for customize your divider in a RecyclerView

You can look that : My custom ItemDecoration use getItemOffsets() like this :

public class MyItemDecoration extends RecyclerView.ItemDecoration {

    private final int decorationHeight;
    private Context context;

    public MyItemDecoration(Context context) {
        this.context = context;
        decorationHeight = context.getResources().getDimensionPixelSize(R.dimen.decoration_height);
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);

        if (parent != null && view != null) {

            int itemPosition = parent.getChildAdapterPosition(view);
            int totalCount = parent.getAdapter().getItemCount();

            if (itemPosition >= 0 && itemPosition < totalCount - 1) {
                outRect.bottom = decorationHeight;
            }

        }

    }
}

Then you can set your R.dimen.decoration_height to the value what you want.

And in my activity, when I instantiate my RecyclerListView I need to do this :

myList.addItemDecoration(MyItemDecoration(this))
myList.setLayoutManager(LinearLayoutManager(this))
myList.setAdapter(adapter)

I hope this will help you

Solution 2

Remove this line from your CardView item .xml

android:layout_margin="5dp"

You probably wanted it to be padding instead of margin

Solution 3

In order to create spacings in between items, we could use RecyclerView's ItemDecorator's:

addItemDecoration(object : RecyclerView.ItemDecoration() {

    override fun getItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State,
    ) {
        super.getItemOffsets(outRect, view, parent, state)
        if (parent.getChildAdapterPosition(view) > 0) {
            outRect.top = 8.dp // Change this value with anything you want. Remember that you need to convert integers to pixels if you are working with dps :)
        }
    }
})

A few things to have in consideration given the code I pasted:

  • You don't really need to call super.getItemOffsets but I chose to, because I want to extend the behavior defined by the base class. If the library got an update doing more logic behind the scenes, we would miss it.

  • As an alternative to adding top spacing to the Rect, you could also add bottom spacing, but the logic related to getting the last item of the adapter is more complex, so this might be slightly better.

  • I used an extension property to convert a simple integer to dps: 8.dp. Something like this might work:

val Int.dp: Int
    get() = (this * Resources.getSystem().displayMetrics.density + 0.5f).toInt()

// Extension function works too, but invoking it would become something like 8.dp()

Solution 4

CardView by default adds padding. Try using CardView attribute card_view:contentPadding but set the negative values for the attribute like this

card_view:contentPadding="-3"

Share:
11,487
quaker
Author by

quaker

Updated on June 05, 2022

Comments

  • quaker
    quaker almost 2 years

    first of all, sorry if this a stupid question. I'm not being lazy. So, the problem is, im trying to implement CardView/RecyclerView in an Android app. I made it, but the problem is that the cards are spaced one from another, and i don't know how to fix it. I explored the code but everything seems to be fine.

    The code :

    RecyclerView

    <android.support.v7.widget.RecyclerView
            android:id="@+id/collapsing_recyclerview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scrollbars="vertical"
            android:padding="@dimen/activity_horizontal_margin">
    
     </android.support.v7.widget.RecyclerView>
    

    CardView item

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <android.support.v7.widget.CardView
        android:id="@+id/card_view"
        card_view:cardBackgroundColor="@color/colorAccent"
        android:layout_gravity="center"
        android:layout_width="fill_parent"
        android:layout_height="100dp"
        android:layout_margin="5dp"
        card_view:cardCornerRadius="2dp">
    
        <TextView
            android:gravity="center"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="New Text"
            android:id="@+id/cardview.name" />
    
    </android.support.v7.widget.CardView>
    
    
    </LinearLayout>
    

    Adapter :

    public class MyRecyclerViewAdapter extends RecyclerView
        .Adapter<MyRecyclerViewAdapter
        .DataObjectHolder> {
    private static String LOG_TAG = "MyRecyclerViewAdapter";
    private ArrayList<CardViewItem> mDataset;
    private static MyClickListener myClickListener;
    
    public static class DataObjectHolder extends RecyclerView.ViewHolder
            implements View
            .OnClickListener {
        TextView label;
    
        public DataObjectHolder(View itemView) {
            super(itemView);
            label = (TextView) itemView.findViewById(R.id.cardview_name);
            Log.i(LOG_TAG, "Adding Listener");
            itemView.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            myClickListener.onItemClick(getAdapterPosition(), v);
        }
    }
    
    public void setOnItemClickListener(MyClickListener myClickListener) {
        this.myClickListener = myClickListener;
    }
    
    public MyRecyclerViewAdapter(ArrayList<CardViewItem> myDataset) {
        mDataset = myDataset;
    }
    
    @Override
    public DataObjectHolder onCreateViewHolder(ViewGroup parent,
                                               int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.example_card_view, parent, false);
    
        DataObjectHolder dataObjectHolder = new DataObjectHolder(view);
        return dataObjectHolder;
    }
    
    @Override
    public void onBindViewHolder(DataObjectHolder holder, int position) {
        holder.label.setText(mDataset.get(position).getName());;
    }
    
    public void addItem(CardViewItem dataObj, int index) {
        mDataset.add(index, dataObj);
        notifyItemInserted(index);
    }
    
    public void deleteItem(int index) {
        mDataset.remove(index);
        notifyItemRemoved(index);
    }
    
    @Override
    public int getItemCount() {
        return mDataset.size();
    }
    
    public interface MyClickListener {
        public void onItemClick(int position, View v);
    }
    }
    

    Hope you guys can help me. Thanks!

    EDIT: So, i found the answer. The coulprit was the android:layout_height="match_parent" in my cardview item. I change it for "wrap_content" and fixed the problem. Thanks for the help guys! :)

  • quaker
    quaker over 7 years
    Hi, thank you for helping. Unfortunatly this doesn't fix the problem :/