How to set the height of an item row in GridLayoutManager

71,614

Solution 1

When inflating layout for your views in adapter, you can set their height programmatically. In order to evaluate proper height to use you can rely on parent ViewGroup (that is the RecyclerView itself). Here it is a sample:

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = mLayoutInflater.inflate(R.layout.view_item, parent, false);
    // work here if you need to control height of your items
    // keep in mind that parent is RecyclerView in this case
    int height = parent.getMeasuredHeight() / 4;
    itemView.setMinimumHeight(height);
    return new ItemViewHolder(itemView);        
}

Hope this could help.

Solution 2

As of support library 25.1.0, ABOVE ANSWER DOESN'T WORK. I suggest below modifications:

    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
        GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams) v.getLayoutParams();
        lp.height = parent.getMeasuredHeight() / 4;
        v.setLayoutParams(lp);
        return new ViewHolder(v);
    }

Solution 3

You don't need to set the height of an item. The problem here is that image tries to fill all the space. Just add android:adjustViewBounds="true" to your ImageView and it will not add blank spaces

Solution 4

v.getLayoutParams().width = parent.getMeasuredWidth() / 2;

v.getLayoutParams().height = parent.getMeasuredWidth() / 2;

Solution 5

kotlin version

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val binding = ItemBinding.inflate(
        LayoutInflater.from(parent.context),
        parent,
        false
    )
    binding.root.post {
        binding.root.layoutParams.height = parent.width/3
        binding.root.requestLayout()
    }
    return ViewHolder(binding)
}

here 3 is the span count of your GridLayoutManager . You can replace binding.root with your itemView , if you are not using Databinding

Share:
71,614
Kunal
Author by

Kunal

Updated on March 24, 2021

Comments

  • Kunal
    Kunal over 3 years

    Current View is

    My Recycler Item which inflate in onCreateViewHolder

    <?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:gravity="center"
        android:orientation="vertical"
        android:padding="16dp">
    
        <ImageView
            android:id="@+id/gridListImageView"
            android:layout_width="96dp"
            android:layout_height="96dp"
            android:src="@drawable/a" />
    
        <TextView
            android:id="@+id/gridListView_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="Large Text"
            android:textAppearance="?android:attr/textAppearanceLarge" />
    </LinearLayout>
    

    I want to display something like this Which has one row of half the height of recycler View? And add padding to the rest of the space? Can i do this by GridLayoutManager?

    And this is my GridLayoutManager

            GridLayoutManager glm = new GridLayoutManager(getActivity(), 2);
            recyclerView.setLayoutManager(glm);
    
  • Huy Tower
    Huy Tower over 7 years
    Hello @thetonrifles, I tried your sample code already but looks like not help me in (this case)[stackoverflow.com/questions/41338627/… that I don't know why. Please help me take a look. Thank you,
  • drindt
    drindt over 7 years
    It seems that as of version recyclerview-v7:25.1.1 doesn't support or misbehave now. By invoking parent.getMeasuredHeight() the return value is always zero.
  • drindt
    drindt over 7 years
    I just tested to ensure this and switched back as your project uses version 23.1.1 and now it works.
  • thetonrifles
    thetonrifles over 7 years
    @drindt Thanks for raising this. I will take a look at this and provide an update to the answer!
  • shoke
    shoke about 7 years
    Did you figure out a way to deal with this with the new recyclerview api? I'm getting 0 for parent.getMeasuredHeight() still
  • thetonrifles
    thetonrifles about 7 years
    @clu Interesting... I tried but I didn't got the same issue. I can try again (since I was doing this some time ago). Of course feel free to share things that might look relevant in your implementation and that maybe I'm not considering right now.
  • Itay Bianco
    Itay Bianco almost 7 years
    nice solution, but 2 questions: 1) how can you be sure onMeasure was called when the runnable runs? 2) what is DataBindingViewHolder?
  • tung
    tung about 6 years
    pls add some more information to your answer like why it's correct or what differs to other answers
  • Pranav Goswami
    Pranav Goswami about 6 years
    none of the above works for me, but this one does. tell what other information you need? do you want me to post full function here?
  • tung
    tung about 6 years
    like what is different from your solution to the others or why this is correct or what you do and why stuff like this
  • AskNilesh
    AskNilesh over 5 years
    @PranavGoswami i just formated your answer not edited kindly check again
  • M. Reza Nasirloo
    M. Reza Nasirloo almost 5 years
    Thank you, If someone needed to use FrameLayout for forground ripple effect on an ImageView in a RecyclerView, this is the way to go.
  • Gopal Singh Sirvi
    Gopal Singh Sirvi almost 4 years
    why divided by 4 ?
  • Gopal Singh Sirvi
    Gopal Singh Sirvi almost 4 years
    why did you divide it by 4?
  • Axay Prajapati
    Axay Prajapati over 3 years
    @GopalSinghSirvi if the guy wants 4 row, divide by 6, if required 6 rows.
  • JP711
    JP711 over 2 years
    What if I need a different height for each row? I have posted a question but haven't been answered link