使用 ConstraintLayout 时 ScrollView 的底部被剪裁

Posted

技术标签:

【中文标题】使用 ConstraintLayout 时 ScrollView 的底部被剪裁【英文标题】:Bottom of ScrollView clipped when using ConstraintLayout 【发布时间】:2017-03-30 23:09:22 【问题描述】:

ConstraintLayout (constraint-layout:1.0.0-beta3) 中使用ScrollView 时遇到问题

我的 ScrollView 的内容没有完全显示出来。

这是我的布局:

<android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_test"
    android:layout_
    android:layout_>

    <LinearLayout
        android:id="@+id/header"
        android:layout_
        android:layout_
        android:orientation="horizontal"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:background="#212121">

        <TextView
            android:layout_
            android:layout_
            android:text="Constraint Layout"
            android:textSize="45sp"/>

    </LinearLayout>

    <ScrollView
        android:layout_
        android:layout_
        app:layout_constraintTop_toBottomOf="@+id/header"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent">

        <LinearLayout
            android:layout_
            android:layout_
            android:orientation="vertical">

            <Button
                android:layout_
                android:layout_
                android:text="BUTTON"
                android:layout_marginTop="800dp"/>


        </LinearLayout>

    </ScrollView>

</android.support.constraint.ConstraintLayout>

这是结果

如您所见,该按钮不可见,我到达了 ScrollView 的底部。

它似乎与下面布局的 LinearLayout 配合得很好

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_test"
    android:layout_
    android:layout_
    android:orientation="vertical">

    <LinearLayout
        android:layout_
        android:layout_
        android:orientation="horizontal"
        android:background="#212121">

        <TextView
            android:layout_
            android:layout_
            android:text="Linear Layout"
            android:textSize="45sp"/>

    </LinearLayout>

    <ScrollView
        android:layout_
        android:layout_>

        <LinearLayout
            android:layout_
            android:layout_
            android:orientation="vertical">

            <Button
                android:layout_
                android:layout_
                android:text="BUTTON"
                android:layout_marginTop="800dp"/>


        </LinearLayout>

    </ScrollView>

</LinearLayout>

结果是

有了LinearLayout,ScrollView的末端是可达的。

ConstraintLayout 有错误还是我做错了什么?

【问题讨论】:

按钮上的 android:layout_marginTop="800dp" 看起来有点粗略...您是否希望按钮始终显示在屏幕底部,并让 ScrollView 位于其顶部?跨度> 这个marginTop是一个强制Button只有在滚动到ScrollView底部后才可见的例子。我想用一个小例子来说明这种行为。 【参考方案1】:

我会这样做的方式是:

<android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_test"
    android:layout_
    android:layout_>

    <TextView
        android:id="@+id/header"
        android:layout_
        android:layout_
        android:background="#212121"
        android:text="Constraint Layout"
        android:textSize="45sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ScrollView
        android:layout_
        android:layout_
        android:fillViewport="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/header">

        <android.support.constraint.ConstraintLayout
            android:layout_
            android:layout_>

            <Button
                android:layout_
                android:layout_
                android:layout_gravity="bottom"
                android:text="BUTTON"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent" />

        </android.support.constraint.ConstraintLayout>

    </ScrollView>

</android.support.constraint.ConstraintLayout>

这给出了:

需要注意的几点:

标题不需要线性布局,直接使用textview即可。 不要使用match_parent,它可能看起来有效,但未定义。使用 0dp 代替正确的约束来根据需要拉伸视图。 显然,不要使用 800dp 边距。它在您的特定屏幕上可能看起来不错,但无法在不同的设备上为您提供所需的内容。 默认情况下,scrollview 会包装其内容——fillViewport 属性是为了让它占据指定的空间 您可以在有意义的情况下使用嵌套的 ConstraintLayout。未来,我们也可能会利用它来做一些性能提升

【讨论】:

感谢您的精确:)【参考方案2】:

我将ScrollView 的高度更改为match_parent 并添加了底部约束。这似乎使它正常工作。

    <ScrollView
        android:layout_
        android:layout_
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/header"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent">

注意:在任何布局中,垂直滚动视图上的高度为 wrap_content 通常都不会很好地结束。

【讨论】:

确实,我的问题来自那里。谢谢! 实际上——在 ConstraintLayout 中不支持 match_parent,所以它不会像你想象的那样做。它似乎在您的示例中有效,但它可能会在其他设备上被破坏。虽然您可以复制 match_parent 行为,但您必须明确定义约束。见***.com/questions/40633299/… @NicolasRoard 我必须同时做这两件事——将高度设置为match_parent 并添加底部约束——以使布局正确。做一个或另一个是不够的。 @krislarson 看到我的答案—— match_parent 未使用 ConstraintLayout 定义。 你可以使用0dp而不是match_parent作为layout_height,效果很好。

以上是关于使用 ConstraintLayout 时 ScrollView 的底部被剪裁的主要内容,如果未能解决你的问题,请参考以下文章

Android ConstraintLayout的基本使用

android.view.InflateException:膨胀类 androidx.constraintlayout.widget.ConstraintLayout 时出错

在 ConstraintLayout 中滚动 RecyclerView 时如何折叠工具栏?

Android开发 - 掌握ConstraintLayout复杂动画!如此简单!

MotionLayout 和 ConstraintLayout 不围绕儿童高度设置动画

Android开发 - 掌握ConstraintLayout偏差(Bias)