79

So my layout looks basically like this:

<ScrollView>
    <RelativeLayout>
        <BunchOfViews/>
        <ImageView android:layout_alignParentBottom="true"/>
    </RelativeLayout>
</ScrollView>

I have the ScrollView so all of the layout always is visible no matter the height of the screen. The problem is that on a very high screen, I still want my ImageView to be at the bottom. However, a child of a ScrollView don't seem to have a defined bottom. The View is placed at the top of the layout. How can I solve this problem in a neat way?

Vasily Kabunov
  • 6,511
  • 13
  • 49
  • 53
pgsandstrom
  • 14,361
  • 13
  • 70
  • 104

9 Answers9

169

I ran into the same issue. I never could find a very pleasing solution, but here is how I did it. Maybe someone else has a better way, I hate adding layouts that don't do anything.

My hack was to add a dummy linearlayout at the bottom of the scrollview that has fill_parent to take up all the room and force the scrollview to fill the screen. Then add whatever component I want to that linearlayout.

Here is one of my layouts that does this:

<ScrollView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1"
    android:fillViewport="true" >

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_marginTop="15px" >

        <!-- bunch of components here -->

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_below="@+id/spinner"
            android:layout_marginTop="5px"
            android:gravity="center_horizontal|bottom"
            android:paddingTop="2px" >

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingLeft="20px"
                android:paddingRight="20px"
                android:text="Delete" />
        </LinearLayout>
    </RelativeLayout>
</ScrollView>
mufazmi
  • 1,103
  • 4
  • 18
  • 37
dweebo
  • 3,222
  • 1
  • 17
  • 19
  • @dweebo I don't get it. It didn't work for me. Can you be more specific with your code demonstration, and show where the ends? – IgorGanapolsky May 23 '12 at 01:25
  • 66
    android:fillViewport is the important part of the trick, and it's easy to miss. – daniel.gindi Dec 31 '13 at 10:49
  • 2
    The 'android:layout_below="@+id/spinner"' part should probably not specify the '+' before 'id'...presumably this is not the place where that id is being defined for the first time (it would be defined somewhere in the "bunch of components here" section, and there it would have the +id) – jimmyorr Oct 21 '14 at 19:30
  • really Help full for me.. Thanks :) We can it my dimen.xml file also but its depends upon the client requirement – sharma_kunal Jan 30 '16 at 23:02
  • This worked for me, but I had to set the background to inner LinearLayout to transparent to see the views behind it. - android:background="@android:color/transparent" – karthik prasad Nov 07 '16 at 18:10
  • What is this sorcery... It worked, but in the bottom layout I wanted to add 24dp bottom margin. It didn't work, padding either. Then I added both and ... it worked (but didn't add up). I don't know why though. – Makalele Nov 11 '16 at 19:04
  • 1
    fill_parent is deprecated. This answer on this same question is more up tod ate https://stackoverflow.com/a/41120823/2614353 – Tom Bevelander Apr 24 '19 at 12:40
83

I had the same issue and found this page:

http://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/

Basically, you set the ScrollView's android:fillViewport to true, which will allow the child view to expand to the same height as the ScrollView itself, filling out the space. You then just need to have one of the child controls' layout_height set to fill_parent and layout_weight to 1, causing that control to "spring" to fill the empty space.

Note that if the contents of the ScrollView are already tall enough to fill the ScrollView, the android:fillViewport has no effect, so the setting only kicks in when needed.

My final XML looks like similar to this:

<ScrollView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:fillViewport="true">
    <LinearLayout
        android:orientation="vertical"
        android:layout_height="wrap_content">
        <LinearLayout
            android:layout_height="fill_parent"
            android:layout_weight="1">
            <!-- this expands to fill the empty space if needed -->
        </LinearLayout>

        <!-- this sits at the bottom of the ScrollView,
        getting pushed out of view if the ScrollView's
        content is tall enough -->
        <ImageView
            android:layout_height="wrap_content"
            android:src="@drawable/footer_image">
        </ImageView>
    </LinearLayout>
</ScrollView>
Joel Malone
  • 1,214
  • 1
  • 12
  • 20
  • 1
    This is great, however my item that is filling the screen is an EditText, and is being allowed to grow below the bottom of the screen in the event that there are a large number of lines typed. Is there a way to prevent this so that the scroll view kicks in only when the soft keyboard is displayed? – finiteloop May 15 '11 at 16:50
  • Thanks a lot, working like charm for me, it also works for nested scrollview, I think there are two things to keep in mind for this - 1 - add `android:fillViewport="true"` to ScrollView or NestedScrollView. 2 - set `android:layout_weight="1"` to inner LinearLayout. here is link for the same solution offered by Romain Guy [link](http://www.curious-creature.com/2010/08/15/scrollviews-handy-trick/) – shivam Apr 04 '17 at 06:30
  • as suggested by android studio, use: `android:layout_height="0dp"` for the expandable layout – andreaciri Jul 07 '18 at 08:38
21

it seems that the linearlayout isn't necessary, all that is important is the fillViewPort. you could just use

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottomParent="true">

now that you have specified the relativelayout to be at least the size of the screen.

mufazmi
  • 1,103
  • 4
  • 18
  • 37
Laurent
  • 211
  • 2
  • 2
10

Joel Malone's answer Adding view to bottom of layout inside a scrollview does that trick. My solution is almost the same, except that I use Space widget to do the work of filling the rest height inside the parent layout. Like this:

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true"
    >
    <LinearLayout
        android:orientation="vertical"
        android:layout_height="wrap_content"
        >
        <android.support.v4.widget.Space
            android:layout_height="match_parent"
            android:layout_weight="1"
            />
    <ImageView
        android:layout_height="wrap_content"
        android:src="@drawable/footer_image"
        />
    </LinearLayout>
</ScrollView>

Attention:

  • fill_parent in the other answers is noted as deprecated for a long time;
  • Compare to an empty LinearLayout to fill the rest of parent layout, I think Space is much more appropriate(it's designed to do that job.)
  • Finally, don't forget that important attribute at the beginning of ScrollView: android:fillViewport="true". They together make this trick.
mufazmi
  • 1,103
  • 4
  • 18
  • 37
Anthonyeef
  • 2,595
  • 1
  • 27
  • 25
  • 1
    While the highest rated approaches work, this is my favorite solution. Using Space is a nice trick which does not require an extra nested layout but still works with multiple "bottom-attached" elements. – Peter F Oct 18 '17 at 13:10
  • One remark: Since `layout_weight="1"` is set, the height of Space should be set to `"0dp"`. Setting the height to `"match_parent"` will show the same result but show a warning in Android Studio. – Peter F Oct 19 '17 at 09:03
  • 1
    @PeterF that's correct; I personally like to set the height to match_parent(more understandable). Since the IDE say so, it should be recommanded to be set to 0dp. – Anthonyeef Oct 19 '17 at 14:55
1

On your view that you want to be at the bottom use android:gravity="bottom"

mufazmi
  • 1,103
  • 4
  • 18
  • 37
hitch45
  • 472
  • 4
  • 12
0

From: http://code.google.com/p/k9mail/source/browse/k9mail/trunk/res/layout/account_setup_basics.xml?r=1314

This should help you:

<RelativeLayout
        android:layout_marginTop="-45dip" 
        android:padding="0dip"
        android:layout_alignParentBottom="true"
        android:gravity="bottom|right" 
        android:background="@android:drawable/bottom_bar"
        android:layout_height="fill_parent"
        android:layout_width="fill_parent">
        <Button
            android:id="@+id/manual_setup"
            android:text="@string/account_setup_basics_manual_setup_action"
            android:minWidth="@dimen/button_minWidth"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:layout_marginBottom="-4dip" 
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="false" 
            />
        <Button
            android:id="@+id/next"
            android:text="@string/next_action"
            android:minWidth="@dimen/button_minWidth"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:drawableRight="@drawable/button_indicator_next"
            android:layout_marginBottom="-4dip" 
            android:layout_alignParentRight="true"
            android:layout_centerVertical="false" 
            />
    </RelativeLayout>
Pentium10
  • 204,586
  • 122
  • 423
  • 502
  • Im sorry, but I dont think I was clear enough. I still want the imageview to be a part of the scrollview, as in my current layout. It should just be at the bottom of the scrollview. And if the scrollview is shorter then the screen, then the imageview should still be at the bottom of the screen. – pgsandstrom Mar 10 '10 at 14:22
  • Also I dont quite understand the effect of having negative numbers on the pixel numbers. I have never used these. So maybe I just have not understood what you were trying to say. If so, could you please elaborate? :P Thanks. – pgsandstrom Mar 10 '10 at 14:24
  • 1
    I don't understand why you need the scrollview if your content does not fill the screen. Using a `android:gravity="bottom|right" ` on a view should put on the bottom. The negative values probably are meant to cut off excessive padding inside button's layout. – Pentium10 Mar 10 '10 at 14:40
0

I tried alot to align the Scroll View to bottom of the screen but thats not possible according to this link. https://newbedev.com/how-do-i-align-views-at-the-bottom-of-the-screen

The way i found was to create a view with 1dp height and aa id (lets say android:id="@+id/bottomView") at the bottom of your XML page.

now just add these attributes to your scroll view..

<ScrollView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:scrollbars="vertical"
        android:fillViewport="true"
        android:layout_alignBottom="@+id/bottomView"
        >
Dharman
  • 30,962
  • 25
  • 85
  • 135
danklad
  • 88
  • 8
0

Here is how you can use a ConstraintLayout to align the image view at the bottom:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/content_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/text_view"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="Text 1"
            app:layout_constraintBottom_toTopOf="@+id/space_view"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="parent" />

        <Space
            android:id="@+id/space_view"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            app:layout_constraintBottom_toTopOf="@+id/image_view"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/text_view" />

        <ImageView
            android:id="@+id/image_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="..."
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/space_view" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</ScrollView>
JJD
  • 50,076
  • 60
  • 203
  • 339
0
ScrollView view = new ScrollView( this );
ScrollView.LayoutParams lps = new FrameLayout.LayoutParams( FILL_PARENT, FILL_PARENT, Gravity.CENTER );
LinearLayout layout = new LinearLayout( this );
// what ever you want in the Layout 
view.addView( layout, lps );
Shibly
  • 11
  • 1