【问题标题】:How can I make a ScrollView fill the rest of its parent's remaining space?如何让 ScrollView 填充其父级的剩余空间?
【发布时间】:2021-06-17 01:42:39
【问题描述】:

我有两个 TextViews 和一个 ScrollView 嵌套在 ConstraintLayout 中。在ScrollView 里面有一个TableLayout。 ScrollView 的左、右和下约束设置为“父”。顶部约束设置为它之前的 TextView。这是 XML:

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom">

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:text="TextView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView"
        android:textSize="16dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView2" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView6">

        <TableLayout
            android:layout_width="fill_parent"
            android:layout_height="match_parent"
            android:layout_marginStart="32dp"
            android:layout_marginTop="32dp"
            android:layout_marginEnd="32dp"
            android:layout_marginBottom="32dp"
            android:gravity="center"
            android:stretchColumns="0,1,2,3,4">

            <TableRow
                android:layout_width="fill_parent"
                android:layout_weight="1">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:text="1" />
                    ... 4 more TextViews
            </TableRow>
            ... many more TableRows
        </TableLayout>
    </ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

问题是 ScrollView 的宽度与其约束不匹配。相反,当添加更多行以使 ScrollView 高于其父级的剩余高度时,它会与之前的 TextView 重叠。下面的两张截图说明了这个问题:

无重叠:

重叠:

当我将 ScrollView 高度设置为“0dp”(匹配约束)时,它按字面意思呈现为 0dp(ScrollView 缩小并且不显示任何内容)。

我应该改变什么以使 ScrollView 展开并填充其父容器的剩余高度?

【问题讨论】:

    标签: android scrollview android-constraintlayout


    【解决方案1】:

    您需要正确约束您的小部件,以便 ConstraintLayout 能够正确测量和布置您的视图。

    简而言之:

    1. Top TextView 需要是垂直链的头部(app:layout_constraintVertical_chainStyle="packed"),并且必须有底部约束(bottom_to_Topof...):
        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:layout_marginEnd="16dp"
            android:text="TextView"
            app:layout_constrainedHeight="true"
            app:layout_constraintVertical_chainStyle="packed"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toTopOf="@id/textView6" />
    

    textView 为constrainedHeight = true,因为您希望它为wrap_content,而具有文本的小部件在包装在约束布局中时可能会出现一些问题(请参阅this other answer,了解有关为什么需要这样做的更多信息)。

    第二个 TextView,也需要固定到某个底部,在这种情况下是 scrollView...

        <TextView
            android:id="@+id/textView6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constrainedHeight="true"
            android:text="TextView"
            android:textSize="16dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView2"
            app:layout_constraintBottom_toTopOf="@id/scrollView" />
    

    现在它们被链接在一起了,但是 ScrollView 需要一些操作...

    只需将滚动视图固定到底部,这样它就可以从某个地方拉动,并给它你需要的 0dp,这样它就可以根据约束计算它的大小/位置。

    <ScrollView
            android:id="@+id/scrollView"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView6">
    
    

    (也给它一个名字/id...)

    这会导致 CL 正确计算空间/大小并避免您抱怨的重叠,因为它现在对可以去哪里有明确的规则。

    当您省略约束(如底部)时,尤其是当周围有像 ScrollViews 这样的愚蠢小部件时,您可能会根据内容产生不可预测的行为,这是难以预料和修复的。如有疑问,请始终尝试为所有小部件提供所有可能的约束。

    【讨论】:

    • 谢谢,但问题仍然存在。 0dp 字面意思是“0dp”(零高度)。然而 0dp 宽度正确呈现(扩展以填充父级)。
    • 如果不看全貌,很难看出您的问题是什么。 0dp 并不意味着零高度,它是 CL 使用的一个特殊值,用于知道某些小部件的大小将由其约束(当然,也由布局中的其他视图)决定。如果滚动视图以“0 高度”呈现,则意味着您缺少约束,或者 CL 没有足够的信息来计算它;这可能是由于多种原因,甚至时间也可能是其中之一;取决于您何时“填充”滚动视图,也会对此产生影响。
    • 非常感谢,是的,约束有问题。
    【解决方案2】:

    我会提出几点建议(我不知道哪一点是关键的):

    1.您不应将 match_parent 用于 ConstraintLayout 的子视图。相反,请使用“0dp”。

    Official training:

    注意:您不能将 match_parent 用于 ConstraintLayout 中的任何视图。而是使用“匹配约束”(0dp)。

    2。你不应该使用@+id/xxx,而是使用@id/xxx来指定其他视图。前者用于创建新的id。

    1. 将 ConstraintLayout 的 layout_height 更改为 match_parent

    2. 将 TableLayout 的 layout_height 更改为 wrap_content

    我的结果:

    layout.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout 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"
        tools:context=".MainActivity">
    
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="bottom">
    
            <TextView
                android:id="@+id/textView2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="16dp"
                android:text="TextView"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
    
            <TextView
                android:id="@+id/textView6"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="TextView"
                android:textSize="16dp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/textView2" />
    
            <ScrollView
                android:layout_width="0dp"
                android:layout_height="0dp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/textView6">
    
                <TableLayout
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="32dp"
                    android:layout_marginTop="32dp"
                    android:layout_marginEnd="32dp"
                    android:layout_marginBottom="32dp"
                    android:gravity="center"
                    android:stretchColumns="0,1,2,3,4">
    
                    <TableRow
                        android:layout_width="fill_parent"
                        android:layout_weight="1">
    
                        <TextView
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            android:text="1" />
    
                        <TextView
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            android:text="2" />
    
                        <TextView
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            android:text="3" />
    
                        <TextView
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            android:text="4" />
    
                        <TextView
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            android:text="5" />
                    </TableRow>
    
                   <!-- plenty of TableRows... -->
    
                </TableLayout>
            </ScrollView>
        </androidx.constraintlayout.widget.ConstraintLayout>
    </FrameLayout>
    

    【讨论】:

    • IDE (Android Studio) 本身使用@+id 来创建新 id 和引用现有 id,但实际上在引用视图时包含加号或省略它并不重要。至于高度,将其(和宽度)设置为 0dp 并不能解决问题 - 结果如问题所述。
    • @WaisKamal Weird... 在我的布局编辑器中,它似乎没问题(没有重叠)。
    • 你的意思是你附加的照片没有重叠?您可以尝试添加更多行以使表格高于可用高度吗?这就是重叠发生的地方。我不确定这是否重要,但 ConstraintLayout 嵌套在 FrameLayout 中。
    • 您能出示您的代码吗?您可能会遗漏一些东西,因为我得到了完全不同的结果(使用 0dp 时为 0 高度)。此外,ConstraintLayout 必须根据其内容进行扩展(以编程方式设置到某个高度),因此将其高度设置为 match_parent 在这里并不方便。即使我这样设置它也不能正确渲染。
    • @WaisKamal 请检查一下。
    猜你喜欢
    • 2013-03-28
    • 1970-01-01
    • 1970-01-01
    • 2010-11-05
    • 1970-01-01
    • 2012-05-11
    • 2013-04-14
    • 1970-01-01
    相关资源
    最近更新 更多