1

In my RecyclerView adapter I want to set the top margin of the items depending on their position. I only want items after the first item to have a top margin. In my code I set the margin of the RecyclerView item programmatically.

When I try to add an item to the RecyclerView however, the item is not visible. I've looked here and here but my code is still not working. Does it make a difference that I'm setting the margin programmatically inside of a RecyclerView? I tried using LinearLayout.LayoutParams and RecyclerView.LayoutParams but still nothing.

Any help would be appreciated.

UPDATE:

I was using the following code to convert dp to px

int top = (int) TypedValue.applyDimension(
                    TypedValue.COMPLEX_UNIT_DIP,
                    R.dimen.element_row_margin_top,
                    r.getDisplayMetrics()
            );

I was passing the RAW dimension value instead of calling:resources.getDimen().

Here is my onBindViewHolder code:

if (position != 0) {
            
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT
            );

            params.setMargins(0, 10, 0, 0);
            holder.linearLayout.setLayoutParams(params);
        }

Here is my rec_list_item (Contains an Image and 2 TextInputlayouts):

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

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"/>

        <com.google.android.material.textfield.TextInputLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1">

            <com.google.android.material.textfield.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>

        </com.google.android.material.textfield.TextInputLayout>

        <com.google.android.material.textfield.TextInputLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1">

            <com.google.android.material.textfield.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>

        </com.google.android.material.textfield.TextInputLayout>

    </LinearLayout>

ViewHolder code:

@Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent,
                                                    int viewType) {

        LinearLayout item = (LinearLayout) LayoutInflater.from(parent.getContext())
                .inflate(R.layout.rec_list_item, parent, false);

        MyViewHolder vh = new MyViewHolder(item);
        return vh;
    }

public static class MyViewHolder extends RecyclerView.ViewHolder {
        public LinearLayout linearLayout;
        public MyViewHolder(LinearLayout item) {
            super(contributorItem);
            linearLayout = item;
        }
    }
Izak
  • 909
  • 9
  • 24

1 Answers1

1

You just need to grab the current layout params from the ViewHolder LinearLayout before setting the params back; so that you want to change the margin of the current ViewHolder LinearLayout, not creating a one from scratch in order to keep other params as-is.

So, change the onBindViewHolder code to

    if (position != 0) {
        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) 
                                                holder.linearLayout.getLayoutParams();
        params.setMargins(0, 10, 0, 0);
        holder.linearLayout.setLayoutParams(params);
    }

UPDATE:

Add id to the root LinearLayout

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

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        
        ......

Inflate the linearLayout using findViewById in the ViewHolder not by assignment.

public static class MyViewHolder extends RecyclerView.ViewHolder {
        public LinearLayout linearLayout;
        public MyViewHolder(View item) {
            super(contributorItem);
            linearLayout = item.findViewById(R.id.linearlayout); // <<<<<<< inflating the LinearLayout
        }
    }
}

Change the onCreateViewHolder to accept a View instead of a LinearLayout

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent,
                                                int viewType) {

    View item = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.rec_list_item, parent, false);

    MyViewHolder vh = new MyViewHolder(item);
    return vh;
}
Zain
  • 37,492
  • 7
  • 60
  • 84
  • ahhh. your answer makes sense. Going to try it later. – Izak Jul 09 '20 at 22:31
  • hmmmm. just tried your code and it is not working... – Izak Jul 10 '20 at 02:53
  • Should I be using `RecyclerView.MarginLayoutParams` or `ViewGroup.MarginLayoutParams` – Izak Jul 10 '20 at 02:54
  • It worked with me .. can you show which `linearLayout` you use .. I see you don't have any IDs for the root element of the list item – Zain Jul 10 '20 at 02:56
  • I added an `id` to the root `linear layout`. still nothing. I added more code above. Thank you. – Izak Jul 10 '20 at 03:33
  • Ahhh wait a minute! It works! Before passing a pixel value for the margin top I was converting `dp` to `px` - that was causing the problem. I have to fix the conversion code. – Izak Jul 10 '20 at 03:36
  • @Izak thanks for comment.. I just updated the answer in `UPDATE` section .. hope it works now – Zain Jul 10 '20 at 12:54