ScrollView не прокручивается до конца нижнего поля внутреннего LinearLayout

У меня проблемы с фрагментом, состоящим из ScrollView, содержащего LinearLayout. Я пытаюсь создать эффект, при котором LinearLayout имеет белый фон и выглядит как лист бумаги, прокручивающийся на цветном фоне. Я пытаюсь добиться этого, заставляя ScrollView занимать все пространство фрагмента, а затем LinearLayout внутри имеет android:layout_margin="16dp" для создания пространства вокруг «бумаги».

Таким образом, полоса прокрутки ScrollView появляется в области цветного фона, верхнее поле прокручивается вместе с содержимым, а нижнее поле прокручивается только по достижении конца.

К сожалению, в этой конфигурации ScrollView не прокручивается до конца и фактически обрезает очень небольшое количество текста внизу. Я подозреваю, что ScrollView не учитывает поля своего дочернего элемента в вертикальном расстоянии прокрутки. Чтобы решить эту проблему, я завернул LinearLayout в FrameLayout, что решает проблему, но кажется излишним. Любые указатели на то, как устранить этот ненужный контейнер, будут оценены.

Примечание: установка android:padding="16dp" в ScrollView и удаление полей не дает желаемого эффекта, так как отступы постоянно появляются на всех четырех краях, независимо от положения прокрутки.

<?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>

person Graham Lyon    schedule 08.05.2013    source источник
comment
Пробовали установить android:layout_height="fill_parent" на ScrollView?   -  person Adil Soomro    schedule 08.05.2013
comment
@AdilSoomro Да, без радости. Размер ScrollView на самом деле не проблема — он соответствующим образом заполняет доступное ему пространство. Это область прокрутки, которую он предоставляет - он не позволяет прокручивать до самого конца своего содержимого, когда его непосредственный дочерний элемент имеет поле. Я считаю, что проблема вызвана тем, что при расчете области прокрутки не учитывается маржа дочернего элемента.   -  person Graham Lyon    schedule 09.05.2013


Ответы (3)


Я помню, как у меня возникли проблемы с тем, что ScrollView каким-то образом не доходил до конца его содержимого, когда макет содержимого имел верхнее поле. Я решил проблему небольшим хаком, добавив пустой вид в конец 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>

Я также использовал аналогичный пустой вид в начале LinearLayout, чтобы полностью избежать полей сверху/снизу.

РЕДАКТИРОВАТЬ: я только что понял, что вы также хотели, чтобы конец «бумаги» отображался при достижении конца представления. В этом случае вы можете установить цвет фона на TextViews вместо самого макета. Затем убедитесь, что между заголовком и статьей нет полей (используйте отступы в качестве разделения).

EDIT2: я должен научиться проверять, когда вопросы были заданы... Ну, может быть, это все еще помогает кому-то. :)

person J.Nieminen    schedule 24.10.2013

Вопрос старый, но у меня были проблемы с плохим поведением ScrollView при упаковке FrameLayout. Также, похоже, не учитываются поля содержащихся макетов. Вы можете заменить FrameLayout другим LinearLayout с одним дочерним элементом, который должен измеряться правильно. Я бы полностью удалил FrameLayout и просто добавил суммированное поле с отступом во внутреннем макете:

<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">

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="26dp"
            android:background="@color/page_background" >
<!--...-->
person sapht    schedule 28.10.2016

Я бы избавился от FrameLayout и сделал LinearLayout дочерним элементом ScrollView с match_parent, установленным в качестве высоты макета. Если это все еще не работает, рассмотрите возможность замены нижнего поля другим произвольным View с желаемой высотой и фоном в качестве последнего элемента в LinearLayout.

person Wenger    schedule 08.05.2013
comment
Match_parent должен быть в scrollView. И дочерний элемент scrollView должен иметь высоту = wrap_content. - person Alexander Mikhaylov; 08.05.2013
comment
Ах, хороший момент. Последний вариант, вероятно, был бы лучшим тогда. - person Wenger; 08.05.2013
comment
Ни одна из этих комбинаций не решает проблему. Честно говоря, добавление дополнительного представления желаемой высоты полей в конце LinearLayout немного более грубо, чем обертывание его в FrameLayout. Почему ScrollView ведет себя таким образом и игнорирует верхнее и нижнее поля? - person Graham Lyon; 09.05.2013
comment
@GrahamLyon Добавление дополнительного представления на самом деле менее неприятно, потому что оно не влияет на иерархию представлений. Если вы добавите оберточный макет с отступами, он добавит еще один слой в иерархию представлений, что повлияет на скорость рендеринга. - person 4emodan; 20.07.2015