ScrollView not scrolling to the end of inner LinearLayout's bottom margin

Graham Lyon picture Graham Lyon · May 8, 2013 · Viewed 7.1k times · Source

I'm having issues with a Fragment consisting of a ScrollView containing a LinearLayout. I'm trying to create an effect where the LinearLayout has a white background and looks like a piece of paper scrolling on a coloured background. The way that I'm trying to achieve this is by having the ScrollView occupy the full space of the fragment and then the LinearLayout inside has android:layout_margin="16dp" to create the space around the "paper".

This way, the scroll bar of the ScrollView appears in the coloured background area, the margin at the top scrolls away along with the content and the margin at the bottom only scrolls in when one reaches the end.

Unfortunately in this configuration the ScrollView won't scroll all the way to the end and in fact cuts off a very small amount of the text at the bottom. I suspect that the ScrollView isn't taking into account its child's margins in its vertical scrolling distance. To solve this I've wrapped the LinearLayout in a FrameLayout which solves the issue, but seems superfluous. Any pointers on how to eliminate this unneeded container would be appreciated.

Note: setting android:padding="16dp" on the ScrollView and scrapping the margins doesn't have the desired effect, as then the padding appears on all four edges continuously, regardless of scroll position.

<?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="fill_parent"
    android:layout_height="wrap_content"
    tools:context=".ArticleFragment" >

    <!-- This FrameLayout exists purely to force the outer ScrollView to respect
         the margins of the LinearLayout -->
    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="10dp"
            android:layout_margin="16dp"
            android:background="@color/page_background" >

            <TextView
                android:id="@+id/article_title"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:textIsSelectable="true" />

            <TextView
                android:id="@+id/article_content"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:textIsSelectable="true" />

       </LinearLayout>
    </FrameLayout>
</ScrollView>

Answer

J.Nieminen picture J.Nieminen · Oct 24, 2013

I remember having trouble with the ScrollView somehow not making it to the end of it's contents when the content layout had a top margin. I solved the problem with a little hack, adding an empty view to the end of the LinearLayout:

<?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="fill_parent"
    android:layout_height="fill_parent"
    tools:context=".ArticleFragment" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="10dp"
        android:layout_margin="16dp" >

        <TextView
            android:id="@+id/article_title"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textIsSelectable="true"
            android:background="@color/page_background" />

        <TextView
            android:id="@+id/article_content"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:textIsSelectable="true"
            android:background="@color/page_background" />


        <!-- Add a little space to the end -->
        <View
            android:layout_width="fill_parent"
            android:layout_height="30dp" />

   </LinearLayout>
</ScrollView>

I used a similar empty view also in the beginning of the LinearLayout to avoid top/bottom margins completely.

EDIT: I just realised that you also wanted the end of the "paper" to show up when reaching the end of the view. In that case you might want to set the background color to the TextViews instead of the layout itself. Then make sure there's no margin between the title and the article (use padding as separation).

EDIT2: I should learn to check when the questions were asked... Well, maybe this still helps someone. :)