Making Recyclerview Fixed Height and Scrollable
Asked Answered
L

5

9

SOLVED CHECK ANSWER BELOW...

So I am trying to create a comments functionality for my Android app and I want to display the comments inside a recyclerview and then have a button and textview below the recyclerview to add comments. I want to have the recyclerview a certain height and make it scrollable if there are lots of comments because I dont want the users to have to scroll down the screen to find the add button.

I couldn't get it to work so I was wondering if anyone else had that issue.

I have all the adapter and everything set up, I am just having trouble with the recyclerview.

Thanks.

I prob was not clear on what I was trying to accomplish. I am trying to create a cardview where it will display all the comments and the ability to add a new comment. The recyclerview will take up approx 80% of the height and then the last 20% is for the edittext and button.

My XML (Scroll to last cardview where the recyclerview is)

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/scrollview">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:fab="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ProfilePageActivity"
    >

    <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/profilepagetoolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        android:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        android:minHeight="?attr/actionBarSize">

    </android.support.v7.widget.Toolbar>
    <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:layout_marginTop="35dp"
        android:layout_below="@+id/profilepagetoolbar"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:id="@+id/aboutCard">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:gravity="center_vertical"
            android:orientation="vertical"
            android:layout_alignTop="@+id/aboutCard"
            android:focusable="true"
            android:focusableInTouchMode="true">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="4dp"
                android:layout_marginEnd="10dp"
                android:layout_marginStart="10dp"
                android:layout_marginTop="-60dp"
                android:gravity="center_vertical"
                android:maxLines="1"
                android:textColor="@color/text"
                android:textSize="20sp"
                android:text="ABOUT" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1px"
                android:background="@color/dividers" />

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

                <ImageView
                    android:id="@+id/nameicon"
                    android:layout_width="24dp"
                    android:layout_height="24dp"
                    android:layout_margin="8dp"
                    android:transitionName="appIcon"
                    android:background="@drawable/ic_account_circle_black_24dp"/>
                <TextView
                    android:id="@+id/Name"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="4dp"
                    android:layout_marginEnd="10dp"
                    android:layout_marginStart="10dp"
                    android:layout_marginTop="8dp"
                    android:gravity="center_vertical"
                    android:maxLines="1"
                    android:textColor="@color/secondary"
                    android:textSize="20sp" />
            </LinearLayout>

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

                <ImageView
                    android:id="@+id/locationicon"
                    android:layout_width="24dp"
                    android:layout_height="24dp"
                    android:layout_margin="8dp"
                    android:transitionName="appIcon"
                    android:background="@drawable/ic_map_black_24dp"/>
                <TextView
                    android:id="@+id/Location"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="4dp"
                    android:layout_marginEnd="10dp"
                    android:layout_marginStart="10dp"
                    android:layout_marginTop="11dp"
                    android:gravity="center_vertical"
                    android:maxLines="1"
                    android:textColor="@color/secondary"
                    android:textSize="15sp" />
            </LinearLayout>

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

                <ImageView
                    android:id="@+id/websiteIcon"
                    android:layout_width="24dp"
                    android:layout_height="24dp"
                    android:layout_margin="8dp"
                    android:transitionName="appIcon"
                    android:background="@drawable/ic_explore_black_24dp"/>
                <TextView
                    android:id="@+id/Website"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="4dp"
                    android:layout_marginEnd="10dp"
                    android:layout_marginStart="10dp"
                    android:layout_marginTop="11dp"
                    android:gravity="center_vertical"
                    android:maxLines="1"
                    android:textColor="@color/secondary"
                    android:textSize="15sp" />
            </LinearLayout>

        </LinearLayout>
    </android.support.v7.widget.CardView>
    <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:layout_marginTop="35dp"
        android:layout_below="@+id/aboutCard"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:id="@+id/writeComment"
        android:layout_alignParentTop="false"
        android:layout_alignParentBottom="false">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:gravity="center_vertical"
            android:orientation="vertical"
            android:focusable="true"
            android:focusableInTouchMode="true">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="4dp"
                android:layout_marginEnd="10dp"
                android:layout_marginStart="10dp"
                android:layout_marginTop="-100dp"
                android:gravity="center_vertical"
                android:maxLines="1"
                android:textColor="@color/text"
                android:textSize="20sp"
                android:text="Comments" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1px"
                android:background="@color/dividers"
                android:id="@+id/divider"/>

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

                <EditText
                    android:layout_width="244dp"
                    android:layout_height="wrap_content"
                    android:id="@+id/editComment"
                    android:layout_below="@+id/divider"
                    android:textColor="@color/text"
                    android:hint="Write a comment..."/>

                <Button
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="Create"
                    android:id="@+id/btnComment"
                    android:layout_gravity="center_horizontal" />
            </LinearLayout>
        </LinearLayout>
    </android.support.v7.widget.CardView>
    <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clickable="true"
        android:layout_marginTop="20dp"
        android:layout_below="@+id/writeComment"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:id="@+id/commentsCard">

        <LinearLayout
            android:layout_alignParentTop="true"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="4dp"
                android:layout_marginEnd="10dp"
                android:layout_marginStart="10dp"
                android:layout_marginTop="0dp"
                android:gravity="center_vertical"
                android:maxLines="1"
                android:textColor="@color/text"
                android:textSize="20sp"
                android:text="Comments" />

            <android.support.v7.widget.RecyclerView
                android:id="@+id/commentsList"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:focusableInTouchMode="true" />

        </LinearLayout>
    </android.support.v7.widget.CardView>
</RelativeLayout>
</ScrollView>

The second and first comment are being cut off.

enter image description here

Lampe answered 1/9, 2015 at 17:15 Comment(1)
Why not use a FrameLayout?Chen
L
12

So what my problem was that for some reason, Recyclerview didnt wrap_contents. I did some research (thanks stackoverflow) and found out a lot of people were having this issue and they posted solutions for this issue.

Basically, I had to use a customized linearlayoutmanger to fix the issue.

I will post the solution they posted and links to their questions. thanks for whoever tried to help, I appreciate it.

This is the extra file I needed. And then I had to set my recyclerview to use this layout instead of the default one.

public class MyLinearLayoutManager extends LinearLayoutManager {

public MyLinearLayoutManager(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;
        recycler.recycleView(view);
    }
}
}

After that. Change this:

 mProductsRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));

To this:

mRecyclerView.setLayoutManager(new MyLinearLayoutManager(getApplicationContext(),1,false));

Three new paramets(Context, int Orientation, boolean reverse); basically, i put 1 for orientation so it shows vertiacally, and false for revers so it shows up how it is ordered in my List.

Links to other people's question with same problem as me. Nested Recycler view height doesn't wrap its content

Nested Recycler view height doesn't wrap its content

Thanks once again guys. Hope this helps someone else

Lampe answered 4/9, 2015 at 4:57 Comment(3)
I am facing following issue after adapter set - java.lang.IndexOutOfBoundsException: Invalid item position 0(0). Item count:0 any solution?Nellnella
I am also facing the same issue, Did you get any working solution?Borrowing
@Nellnella just put the crashed code inside postDelayed(for 1000 ms)Downtrend
P
6

Add this code in your activity, will set the height of your recycler view to the 90% of user's screen window.

DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);

int a =  (displaymetrics.heightPixels*90)/100;

recylcerView.getLayoutParams().height =a;

and your comment layout below the your recyclerView

like this

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <LinearLayout
        android:layout_alignParentTop="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
        android:id="@+id/mudit"
        >

        <android.support.v7.widget.RecyclerView
            android:id="@+id/my_recycler_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:elevation="5dp"
            android:scrollbars="vertical" />
    </LinearLayout>

    <RelativeLayout
        android:layout_below="@+id/mudit"
        android:id="@+id/rl_commentWrap"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true" >

        <EditText
            android:id="@+id/editText1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:ems="10" />

        <Button
            android:id="@+id/plusButton"
            style="android:buttonStyleSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:text="Send"
            android:textColor="#FFFFFF"
            android:translationZ="5dp" />
    </RelativeLayout>

</RelativeLayout>
Pageantry answered 1/9, 2015 at 17:57 Comment(8)
but how do i get it to scroll if there are more data. Right now it is not doing that, it just cuts it off. The recyclerview wont scrollLampe
Well, recycler view is self scrollable , you should add more views to your recycler view then check;Pageantry
can it be because everything is wrapped inside a scrollview?Lampe
Yes, listview, gridview, recyclerview are self scrollable , you don't wrap them in a Horizontal or Vertical scroll view.Pageantry
Cause right now, I have 3 cardviews on the page, and i needed to wrap everything in <Scrollview> to make it scroll. Now in one of those cardviews which is like around (300dp height), I have a listview and it scrolls perfectly inside that card. I have another cardview with same height and added a recyclerview and it will just get cut off, it wont scroll.Lampe
send me your xml file.Pageantry
I posted the XML.. Thanks for taking time to helpLampe
That's the most optimal solution yet! (unfortunately)... If the recyclerview is not scrolling don't forget to recycler.setNestedScrollingEnabled(true)Mezzanine
M
2

In my situation I had a DialogFragment, in which there are 2 recyclers and 2 horizontal linear layouts with 2 buttons.

Dialog from top to bottom looks like this:

  • RecyclerView A
  • Horizontal linear layout X with 2 buttons
  • RecyclerView B
  • Horizontal linear layout Y with 2 buttons

On top of that both recyclers size is dynamic. Recycler A size can change based on user swipes in both recyclers. Recycler B size can change based on its item click listener.

What I wanted to achieve was to cut the Dialog from top to bottom and have each of those four views its constant part of the Dialog height.

What worked was to divide it first to 2 separate relative layouts, say lTOP and lBottom. Set lTOP alignParentTop, lBottom alignParentBottom and layout_below lTOP. Both of them width match_parent, height wrap_content.

Then in each of them create 1 relative (say lINTop) and 1 linear (say lINBottom) layouts. lINTop has recycler, lINBottom has 2 buttons. Set both lINTop lINBottom width match_parent, height wrap_content. Set lINTop alignParentTop, lINBottom alignParentBottom and below lINTop. Set lINTop orientation vertical, lINBottom orientation horizontal.

Set recyclers width match_parent, height wrap_content.

Then i putted this all inside single relative layout with width/height wrap_content and orientation vertical. Then this inside scrollview with width/height match_parent and orientation vertical.

Then needed a little code magic for setting up recycler in onCreateView:

For Recycler A:

private void setupRecyclerA() {
    // use a linear layout manager
    RecyclerView.LayoutManager layManUS = new LinearLayoutManager(setupActivity().get());
    recyclerA.setLayoutManager(layManUS);
    recyclerA.addItemDecoration(new DividerItemDecoration(
            setupActivity().get(), LinearLayoutManager.VERTICAL));
    recyclerA.setNestedScrollingEnabled(true);
    // use this setting to improve performance if you know that changes
    // in content do not change the layout size of the RecyclerView
    recyclerA.setHasFixedSize(true);
}

For Recycler B:

private void setupRecyclerB() {
    // use a linear layout manager
    RecyclerView.LayoutManager layManUS = new LinearLayoutManager(setupActivity().get());
    recyclerB.setLayoutManager(layManUS);
    recyclerB.addItemDecoration(new DividerItemDecoration(
            setupActivity().get(), LinearLayoutManager.VERTICAL));
    recyclerB.setNestedScrollingEnabled(true);
    // set fixed height
    DisplayMetrics displaymetrics = new DisplayMetrics();
    setupActivity().get().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
    // set height to 30 percent of dialog
    int a =  (displaymetrics.heightPixels*30)/100;
    recyclerB.getLayoutParams().height =a;
    // use this setting to improve performance if you know that changes
    // in content do not change the layout size of the RecyclerView
    recyclerB.setHasFixedSize(true);
}

I didnt invented it, I just combined solutions from many different Stack Overflow questions which I dont even remember now, sorry and thanks to the Creators.

Mccrea answered 4/4, 2019 at 21:28 Comment(0)
A
0

I had a similar problem and solved it with RelativeLayout. I have this layout:

enter image description here

I wanted the top and bottom cardview to stay in place while scrolling the central recyclerView. Tried with LinearLayout and ConstraintLayout but didn't work, the bottom CardView only was shown when I scrolled to the end of the recycler.

This is my code, notice the layout_above, layout_below, and layout_alignParentBottom attributes:

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/grisMasOscuro">

    <androidx.cardview.widget.CardView
        android:id="@+id/cv1"
        android:layout_width="match_parent"
        android:layout_height="50dp" >
        
        <!-- cardview content -->
        
    </androidx.cardview.widget.CardView>
    
    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@id/cv3"
        android:layout_below="@id/cv1">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/myRecyclerView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
            
    </androidx.cardview.widget.CardView>
            
    
    <androidx.cardview.widget.CardView
        android:id="@+id/cv3"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_alignParentBottom="true">
        
        <!-- cardview content -->
        
    </androidx.cardview.widget.CardView>

</RelativeLayout>
Availability answered 18/11, 2021 at 12:49 Comment(0)
P
-3

I found another solution. If you will wrap recyclerview in RelativeLayout, it will solve the problem easily. Thanks.

Pepin answered 23/4, 2018 at 8:50 Comment(1)
Can you provide some more details? I think this would improve your answerDismissal

© 2022 - 2024 — McMap. All rights reserved.