RecycleView leaves empty space at the bottom because of toolbar
B

5

17

Update:

  • Actual issue is with CoordinatorLayout not with RecycleView.
  • Instead of using RecycleView I tried TextView inside ScrollView and it is the same issue.
  • Something is not aligned if you have Toolbar as ActionBar and using CoordinatorLayout with another ToolBar as Sticky Header with scrolling element at bottom

Original:

I'm in process of develop a view which needed Sticky header implementation with recycle view at bottom. I have used Coordinator layout support as describe here.

What is working:

  • Sticky View on scroll list.
    • Toolbar using layout_collapseMode = pin & CollapsingToolbarLayout using layout_scrollFlags = scroll|exitUntilCollapsed|snap property.
    • Recycle view with behaviour app:layout_behavior="@string/appbar_scrolling_view_behavior"

What is issue:

  • Recycle view leaving margin at bottom, it has same size as Toolbar I'm using to sticky view.
  • Recycle view last item does not display, it need extra bottom_margin as size of sticky tool bar view.

Observation:

  • If I fill recycle instant then it work. But if notify it with some delay then it causing issue.
  • Update. In another trial and run**, instead of using Recycle I put an TextView inside the NestedScrollView.(PFA) (not updated in layout here)
    • Here I have added text from xml and after delay of 2 second just append some more text and it's same result.
    • It's layout that take bottom margin again. So nothing specific related to Recycle view, it seems some issue with CoordinatorLayout.

I have tried with multiple solution available here, here, but none of working.

PFA, current output.

enter image description here

Update PFA, experiment with text view with delay.

enter image description here

Here is the layout file.

<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/summaryAppBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/main.collapsing"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="256dp"
                android:background="@drawable/fable_1"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.3" />

            <!-- This is sticky header-->
            <androidx.appcompat.widget.Toolbar
                android:id="@+id/summaryToolBar"
                android:layout_width="match_parent"
                android:layout_height="72dp"
                android:layout_gravity="center"
                android:background="@android:color/white"
                android:padding="@dimen/common_layout_margin"
                android:visibility="visible"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

                <FrameLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:textSize="24sp"
                        android:text="Name" />

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="right"
                        android:textSize="24sp"
                        android:text="Offer"/>

                </FrameLayout>

            </androidx.appcompat.widget.Toolbar>

        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

   <!-- Bottom margin if I do't use then it does not display last child item. Wired but true in this case-->

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        android:visibility="visible"
        android:layout_marginBottom="72dp"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        tools:listItem="@layout/item_dessert" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>
Bricker answered 1/3, 2019 at 7:26 Comment(6)
please share your codeFormless
had you added : android:fitsSystemWindows="true" to your coordinator view?Malodorous
yes, but that pushing layout up and resulting action bar cut from top.Bricker
Don't you have android:layout_marginBottom="72dp" set?Knp
@PFuster so I added issue in What is issue section. Removing of that even not fixing bottom space issue. Please also refer Observation section, that's where I could be able to conclude so far.Bricker
@CoDe: Did you find a solution for this issue? I also have an ugly white bar appearing at the bottom of my RecyclerView when I'm scrolling upwards. It makes my NavBar intransparent. "clipToPadding=false" has no effect. See here the video: github.com/patrickfrei/test_coding/blob/main/issue.webmMild
C
5

Can you please try the below layout file. I have tested it and it works fine. You can remove the marginButtom from the recyclerview as well.

xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">


<androidx.coordinatorlayout.widget.CoordinatorLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.google.android.material.appbar.AppBarLayout
    android:id="@+id/summaryAppBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <com.google.android.material.appbar.CollapsingToolbarLayout
        android:id="@+id/main.collapsing"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="256dp"
            android:background="@drawable/fable_1"
            app:layout_collapseMode="parallax"
            app:layout_collapseParallaxMultiplier="0.3" />

        <!-- This is sticky header-->
        <androidx.appcompat.widget.Toolbar
            android:id="@+id/summaryToolBar"
            android:layout_width="match_parent"
            android:layout_height="72dp"
            android:layout_gravity="center"
            android:background="@android:color/white"
            android:padding="@dimen/common_layout_margin"
            android:visibility="visible"
            app:layout_collapseMode="pin"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

            <FrameLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="24sp"
                    android:text="Name" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="right"
                    android:textSize="24sp"
                    android:text="Offer"/>

            </FrameLayout>

        </androidx.appcompat.widget.Toolbar>

        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>



    <androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    android:visibility="visible"
    android:layout_marginBottom="72dp"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:listItem="@layout/item_dessert" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>
</RelativeLayout>
Cassimere answered 12/3, 2019 at 3:2 Comment(1)
Adding a relative layout as Parent layout fixed this great issue. Thank you Jiten.Bricker
G
6

I believe that the CoordinatorLayout (maybe the AppBarLayout or CollapsingToolbarLayout - not sure which component) is recording the incorrect height of the CollapsingToolbarLayout due to the sticky toolbar. The behavior differs if items are added before or after the initial layout.

Try the following:

  1. Remove android:layout_marginBottom="72dp" from the XML for the RecyclerView.
  2. Add android:minHeight="72dp" to the XML for CollapsingToolbarLayout

Since your sticky toolbar is set at 72dp, it is OK to use minHeight set to 72dp.

If you have trouble with this, post back here.


Here is a quick demo of your layout using a NestedScrollView and the changes mentioned above.

Update: I have worked this out using RecyclerView which displays the same problem. Demo project showing the problem and the fix is on GitHub.

enter image description here

Here is the code:

MainActivity.java

public class MainActivity extends AppCompatActivity {  
    // Set to true to break the layout; false for it to work.  
    // The setting of this flag should only matter for the 
    // layout activity_not_working.  
    private boolean mBreakIt = true;  

    //    private int mLayoutToUse = R.layout.activity_not_working;  
    private int mLayoutToUse = R.layout.activity_working;  

    private LinearLayout mLayout;  

    @Override  
  protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(mLayoutToUse);  

        mLayout = findViewById(R.id.linearLayout);  
        if (mBreakIt) {  
            mLayout.post(new Runnable() {  
                @Override  
  public void run() {  
                    addViews();  
                }  
            });  
        } else {  
            addViews();  
        }  
    }  

    private void addViews() {  
        for (int i = 0; i < 50; i++) {  
            TextView tv = new TextView(MainActivity.this);  
            tv.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,  
                    ViewGroup.LayoutParams.WRAP_CONTENT));  
            tv.setText("TextView #" + (i + 1));  
            mLayout.addView(tv);  
        }  
    }  
}

activity_working.xml

<androidx.coordinatorlayout.widget.CoordinatorLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/summaryAppBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/main.collapsing"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:minHeight="72dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="256dp"
                android:background="@drawable/beach"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.3" />

            <!-- This is sticky header-->
            <androidx.appcompat.widget.Toolbar
                android:id="@+id/summaryToolBar"
                android:layout_width="match_parent"
                android:layout_height="72dp"
                android:layout_gravity="center"
                android:background="@android:color/white"
                android:padding="@dimen/common_layout_margin"
                android:visibility="visible"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

                <FrameLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Name"
                        android:textSize="24sp" />

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="right"
                        android:text="Offer"
                        android:textSize="24sp" />

                </FrameLayout>

            </androidx.appcompat.widget.Toolbar>

        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <!-- Bottom margin if I do't use then it does not display last child item. Wired but true in this case-->
    <!-- Removed following: -->
    <!--android:layout_marginBottom="72dp"-->

    <androidx.core.widget.NestedScrollView
        android:id="@+id/nestedScrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/holo_blue_light"
        android:visibility="visible"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        app:layout_insetEdge="bottom"
        tools:listItem="@layout/item_dessert">

        <LinearLayout
            android:id="@+id/linearLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="A TextView" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="A TextView" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="A TextView" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="A TextView" />


        </LinearLayout>
    </androidx.core.widget.NestedScrollView>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

activity_not_working.xml

<androidx.coordinatorlayout.widget.CoordinatorLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/summaryAppBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/main.collapsing"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="256dp"
                android:background="@drawable/beach"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.3" />

            <!-- This is sticky header-->
            <androidx.appcompat.widget.Toolbar
                android:id="@+id/summaryToolBar"
                android:layout_width="match_parent"
                android:layout_height="72dp"
                android:layout_gravity="center"
                android:background="@android:color/white"
                android:padding="@dimen/common_layout_margin"
                android:visibility="visible"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

                <FrameLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Name"
                        android:textSize="24sp" />

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="right"
                        android:text="Offer"
                        android:textSize="24sp" />

                </FrameLayout>

            </androidx.appcompat.widget.Toolbar>

        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <!-- Bottom margin if I do't use then it does not display last child item. Wired but true in this case-->
    <!-- Removed following: -->
    <!--android:layout_marginBottom="72dp"-->

    <androidx.core.widget.NestedScrollView
        android:id="@+id/nestedScrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="72dp"
        android:background="@android:color/holo_blue_light"
        android:visibility="visible"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        app:layout_insetEdge="bottom"
        tools:listItem="@layout/item_dessert">

        <LinearLayout
            android:id="@+id/linearLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="A TextView" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="A TextView" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="A TextView" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="A TextView" />


        </LinearLayout>
    </androidx.core.widget.NestedScrollView>

</androidx.coordinatorlayout.widget.CoordinatorLayout>
Gaza answered 8/3, 2019 at 22:2 Comment(1)
I tried this but in my case it is same issue. Please note I already have toolbar set as an Action Bar. I'm still on it and will update soon.Bricker
C
5

Can you please try the below layout file. I have tested it and it works fine. You can remove the marginButtom from the recyclerview as well.

xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">


<androidx.coordinatorlayout.widget.CoordinatorLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.google.android.material.appbar.AppBarLayout
    android:id="@+id/summaryAppBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <com.google.android.material.appbar.CollapsingToolbarLayout
        android:id="@+id/main.collapsing"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="256dp"
            android:background="@drawable/fable_1"
            app:layout_collapseMode="parallax"
            app:layout_collapseParallaxMultiplier="0.3" />

        <!-- This is sticky header-->
        <androidx.appcompat.widget.Toolbar
            android:id="@+id/summaryToolBar"
            android:layout_width="match_parent"
            android:layout_height="72dp"
            android:layout_gravity="center"
            android:background="@android:color/white"
            android:padding="@dimen/common_layout_margin"
            android:visibility="visible"
            app:layout_collapseMode="pin"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

            <FrameLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="24sp"
                    android:text="Name" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="right"
                    android:textSize="24sp"
                    android:text="Offer"/>

            </FrameLayout>

        </androidx.appcompat.widget.Toolbar>

        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>



    <androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    android:visibility="visible"
    android:layout_marginBottom="72dp"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:listItem="@layout/item_dessert" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>
</RelativeLayout>
Cassimere answered 12/3, 2019 at 3:2 Comment(1)
Adding a relative layout as Parent layout fixed this great issue. Thank you Jiten.Bricker
A
4

The RecyclerView height is just being calculated wrongfully, when entering scroll. these two different examples only added confusion to the question, without the least Java code provided.

simply remove this one line from the RecyclerView:

android:layout_marginBottom="72dp"

this attribute has little use, because it's the default value:

android:visibility="visible"

don't set the RecyclerView height like this:

android:layout_height="match_parent"

but make it fill up the available space:

android:layout_height="0dp"
android:layout_weight="1.00"

so that the RecyclerView would always fit, in case there is a toolbar present, whether or not - this toolbar just shouldn't be set sticky, because this is what demands halfheartedly "fixing" the layout. a BottomNavigationView might eventually be useful there, depending on what that toolbar, might be good for. even found the source of the script: CoordinatorBehaviorExample, which should have been attributed, as the license requires it.

Antiperistalsis answered 1/3, 2019 at 13:53 Comment(2)
Hi Martin, I have added comment in layout section. About weight property, it will not be possible as direct child of CoordinatorLayout, though putting NestedScrollView and take RecycleView inside LinearLayout also not making any difference.Bricker
Toolbar I'm using as an part of Sticky header, in GIF I have shown with text (Name & Offer label). About BottomNavigationView, not really sure how this can fix it !!Bricker
L
3

I assume there could be issue while adding new data and notify adapter.

You should change from notifyDataSetChanged() to notifyItemInserted(index).

More documentation on notifyItemInserted(index) here.

Hope it helps.

Leukas answered 1/3, 2019 at 9:23 Comment(1)
Hiren, this help to fix issue till some extend but original issue still persist. Please refer updated post.Bricker
R
3

Hey you have set a marginBottom attribute there. Remove that. That's where the error is. The code for the RecyclerView should be:

<androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        tools:listItem="@layout/item_dessert" />
Risley answered 1/3, 2019 at 14:6 Comment(2)
Hi Gourav, it is needed for some weird unknown reason, issue I have added in What is issue section and in layout section comment as well. Please refer.Bricker
android:clipToPadding="false" is what I was looking for... +1Acrospire

© 2022 - 2024 — McMap. All rights reserved.