Search code examples
androidkotlinandroid-activity

How to make a layout fill the screen vertically but start to grow when content doesn't fit


I wish I had an example to show if it seems confusing, but basically what I want to do is show a bottom toolbar with a Right navigator button (e.g. go to next page) always anchored to bottom of the screen, but if the content on the page (middle section) grows, the toolbar will push down so that you have to scroll to get to it. I know it seems strange, but this is the requirements. What would be the best approach for this?


Solution

  • You can achieve this by combining a ScrollView using android:fillViewport="true" and a vertical LinearLayout that has a Space with android:layout_weight="1" between your content and your navigation bar.

    <?xml version="1.0" encoding="utf-8"?>
    <ScrollView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        tools:context=".MainActivity">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
    
            <View
                android:layout_width="match_parent"
                android:layout_height="200dp"
                android:background="#ccc"/>
    
            <Space
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"/>
    
            <View
                android:layout_width="match_parent"
                android:layout_height="48dp"
                android:background="#eee"/>
    
        </LinearLayout>
    
    </ScrollView>
    

    That first view is a placeholder for whatever content you want to display, and the second is a placeholder for your navigation bar. You can see that when the first view is short (200dp tall), you get the "content" at the top and the navigation bar at the bottom:

    This works because the fillViewport attribute will "stretch" the child LinearLayout to fill the screen, at which point there is "extra" space and the layout_weight attribute on the Space element will consume all that space. (Note that, despite being a ScrollView, you can't actually scroll anything in this state, since the view is stretched to be the exact size of the screen.)

    However, when the "content" is tall enough to fill the screen, the fillViewport attribute will have no effect, the LinearLayout won't be stretched, and there won't be any extra space to consume. So, once you scroll to the bottom, your content will fill right up to the edge of the navigation bar:

     

    (Scrolled to the top on the left, and scrolled to the bottom on the right.)