Rahul Surendran
Rahul Surendran

Reputation: 181

How to set different height for each items in recycler View

I want to set a different height for each item in a recycler view. Normally we are getting the same height for every row. But I need different heights, for instance, if the first three rows are 70 in height then I need the remaining with height 0. My code is as follows. In this code its not set properly. Please suggest me an edit

public class MainActivity extends AppCompatActivity {

private RecyclerView rvListProfiles;
private ListProfileAdapter listProfileAdapter;
private String[] list = new String[]{"ABC","DEF","GHI","JKL","MNO"};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    rvListProfiles = findViewById(R.id.rvListProfiles);

    listProfileAdapter = new ListProfileAdapter(list, this);
    RecyclerView.LayoutManager mLayoutManager = new 
    LinearLayoutManager(getApplicationContext());
    rvListProfiles.setLayoutManager(mLayoutManager);
    rvListProfiles.setItemAnimator(new DefaultItemAnimator());
    rvListProfiles.setAdapter(listProfileAdapter);
    String listString = Arrays.toString(list);
    System.out.println("List "+listString);
}
}

item xml

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="70dp"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:background="@android:color/darker_gray"
    android:padding="10dp"
    android:id="@+id/parentLayout">

<ImageView
    android:id="@+id/profileImage"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:layout_alignParentStart="true"
    android:layout_centerVertical="true"
    android:src="@mipmap/love"
    android:transitionName="imageTransition" />

<TextView
    android:id="@+id/profileName"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_marginStart="23dp"
    android:layout_toEndOf="@+id/profileImage"
    android:padding="2dp"
    android:text="TextView"
    android:textColor="@android:color/background_light"
    android:textSize="18sp"
    android:transitionName="nameTransition" />

<TextView
    android:id="@+id/profileDesc"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignBottom="@+id/profileImage"
    android:layout_alignStart="@+id/profileName"
    android:layout_marginTop="5dp"
    android:maxLines="1"
    android:padding="2dp"
    android:text="@string/dummy_data"
    android:textColor="@android:color/background_light"
    android:textSize="12sp"
    android:transitionName="descTransition" />

   </RelativeLayout>

ViewHolder class

public class ListProfileViewHolder extends RecyclerView.ViewHolder {

public ImageView profileImage;
public TextView profileName;
public TextView profileDesc;
public RelativeLayout parentLayout;
public Context context;

public ListProfileViewHolder(View itemView, Context mContext) {
    super(itemView);
    this.context = mContext;
    profileImage = itemView.findViewById(R.id.profileImage);
    profileName = itemView.findViewById(R.id.profileName);
    profileDesc = itemView.findViewById(R.id.profileDesc);
    parentLayout = itemView.findViewById(R.id.parentLayout);
}

}

Adapter Class

public class ListProfileAdapter extends 
RecyclerView.Adapter<ListProfileViewHolder> {

private String[] list;
private Context mContext;
private int height[] = {70,70,70,
                        0,0,0,0};

public ListProfileAdapter(String[] list, Context mContext) {
    this.list = list;
    this.mContext = mContext;
}

@Override
public ListProfileViewHolder onCreateViewHolder(ViewGroup parent, int 
viewType) {
    View layoutView = 
LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, 
null);
    return new ListProfileViewHolder(layoutView, mContext);
}

@Override
public void onBindViewHolder(final ListProfileViewHolder holder, int 
position) {


    holder.parentLayout.setLayoutParams(new 
RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
            height[position]));
    holder.profileName.setText(list[position]);
    holder.profileImage.setOnClickListener(new View.OnClickListener() 
{
     @Override
     public void onClick(View view) {
         Intent sharedIntent = new 
Intent(mContext,SharedActivity.class);
         sharedIntent.putExtra("name",holder.profileName.getText());
         sharedIntent.putExtra("desc",holder.profileDesc.getText());
         Pair[] pairs = new Pair[3];
         pairs[0] = new Pair<View,String> 
(holder.profileImage,"imageTransition");
         pairs[1] = new Pair<View,String> 
(holder.profileName,"nameTransition");
         pairs[2] = new Pair<View,String> 
(holder.profileDesc,"descTransition");

         ActivityOptions options = 
ActivityOptions.makeSceneTransitionAnimation((Activity) 
mContext,pairs);
         mContext.startActivity(sharedIntent,options.toBundle());
     }
 });
    holder.parentLayout.setOnClickListener(new View.OnClickListener() 
{
        @Override
        public void onClick(View view) {
            height = new int[]{0,0,0,
                    70,70,70,70,};
            notifyDataSetChanged();
        }
    });
}

@Override
public int getItemCount() {
    return list.length;
}
}

Upvotes: 8

Views: 12373

Answers (5)

fat eagle
fat eagle

Reputation: 31

In my case, I added views to FlowLayout, but items have all the same height.

solution: In the item layout xml, use RelativeLayout as root only and ensure the layout whose child view be dynamically added is surrounded with RelativeLayout too.

just like this:

<RelativeLayout>
  ...
  <FlowLayout />

</RelativeLayout>

Upvotes: 1

oztrna
oztrna

Reputation: 95

You can try StaggeredGridLayoutManager for asymmetric items.

try change this

RecyclerView.LayoutManager mLayoutManager = new 
    LinearLayoutManager(getApplicationContext());

to this

RecyclerView.LayoutManager mLayoutManager = new 
    StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);

Some of the examples:

1: Staggered GridView

2: StaggeredGridLayout

Upvotes: 1

Alvin Tom
Alvin Tom

Reputation: 119

The height in .xml is in dp(70dp), while in coding is in pixel. So, to get the the size correctly, you need to convert dp to px then apply it programmatically:

Convert dp to px:

public int DpToPx(Activity activity, int dp){
    Resources r  = activity.getResources();
    int px    = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics());
    return px;

}

then apply to your layout param:

holder.parentLayout.setLayoutParams(newRelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
        DPToPx(activity, height[position]));

Upvotes: 1

Pedro Massango
Pedro Massango

Reputation: 5025

Since you are updating the Layout size, you need to refresh the UI, try to call this line after the layout size update:

holder.parentLayout.requestLayout(); //It is necesary to refresh the screen

Upvotes: 0

Harshil kakadiya
Harshil kakadiya

Reputation: 252

try like this.

holder.parentLayout.requestLayout();
            if (position == 0 || position==1 || position==2) {
                holder.parentLayout.getLayoutParams().height = height[position];
            } else {
                holder.parentLayout.getLayoutParams().height = height[position];
            }

Upvotes: 3

Related Questions