Java – Force RecyclerView in the layout to the bottom of the page

Force RecyclerView in the layout to the bottom of the page… here is a solution to the problem.

Force RecyclerView in the layout to the bottom of the page

I have a page with ImageView and RecyclerView. The RecyclerView contains a handful of items (currently three) and only takes up about a quarter of my test device screen. However, despite trying multiple layout options, I couldn’t get RecyclerView to wrap its contents efficiently and take up enough space to include those three rows, leaving the rest of the space for my ImageView.

To help illustrate what I mean, I drew two diagrams. The first shows what I want to happen, and the second shows what’s happening:

This is the Correct Layout This is the current (incorrect) layout

So far, I’ve tried several different combinations of RelativeLayouts – for example, I set RecyclerView to layout:align_ParentBottom, and the second RelativeLayout contains ImageView to layout:alignComponent so that its bottom matches the top of the RecyclerView (this usually drags the ImageView layout so that it fills any remaining space, which is what I want to happen.) )

RecyclerView Although it contains only a few rows, it always occupies all the space it can occupy. My current “solution” is to put everything in LinearLayout and set up less gravity for RecyclerView, but that’s not ideal because on different emulators it won’t align perfectly with the bottom of the screen, and on other emulators there isn’t enough space and RecyclerView Becomes scrollable.

Thanks in advance for any help and advice anyone can provide.

Solution

Many thanks to everyone who contributed, but I found a programming solution outside of the layout file. If someone else is looking for a solution to this problem, I found a here .

RecyclerView seems to have a problem at the moment, it doesn’t wrap the contents. The answer is to construct a custom class that extends the LinearLayoutManager. I’ve posted the solutions below that worked for me – most of them copied and pasted from the answers given in the links I quoted. The only minor problem is that it doesn’t take into account the extra space added by the decoration, which is why I had to make a small tweak to the following line near the end of the code:

//I added the =2 at the end.    
measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin + 2;

The complete code is as follows:

public class HomeLinearLayoutManager extends LinearLayoutManager{

HomeLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

private int[] mMeasuredDimension = new int[2];

@Override
    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
                          int widthSpec, int heightSpec) {
        final int widthMode = View.MeasureSpec.getMode(widthSpec);
        final int heightMode = View.MeasureSpec.getMode(heightSpec);
        final int widthSize = View.MeasureSpec.getSize(widthSpec);
        final int heightSize = View.MeasureSpec.getSize(heightSpec);
        int width = 0;
        int height = 0;
        for (int i = 0; i < getItemCount(); i++) {
            measureScrapChild(recycler, i,
                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                    mMeasuredDimension);

if (getOrientation() == HORIZONTAL) {
                width = width + mMeasuredDimension[0];
                if (i == 0) {
                    height = mMeasuredDimension[1];
                }
            } else {
                height = height + mMeasuredDimension[1];
                if (i == 0) {
                    width = mMeasuredDimension[0];
                }
            }
        }
        switch (widthMode) {
            case View.MeasureSpec.EXACTLY:
                width = widthSize;
            case View.MeasureSpec.AT_MOST:
            case View.MeasureSpec.UNSPECIFIED:
        }

switch (heightMode) {
            case View.MeasureSpec.EXACTLY:
                height = heightSize;
            case View.MeasureSpec.AT_MOST:
            case View.MeasureSpec.UNSPECIFIED:
        }

setMeasuredDimension(width, height);
    }

private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
                                   int heightSpec, int[] measuredDimension) {
        View view = recycler.getViewForPosition(position);
        if (view != null) {
            RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
            int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
                    getPaddingLeft() + getPaddingRight(), p.width);
            int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
                    getPaddingTop() + getPaddingBottom(), p.height);
            view.measure(childWidthSpec, childHeightSpec);
            measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
            measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin + 2;
            recycler.recycleView(view);
        }
    }
}

Thanks again.

Related Problems and Solutions