是否可以将 ConstraintLayout 放在 ScrollView 中?

Posted

技术标签:

【中文标题】是否可以将 ConstraintLayout 放在 ScrollView 中?【英文标题】:Is it possible to put a ConstraintLayout inside a ScrollView? 【发布时间】:2016-09-17 21:43:37 【问题描述】:

最近,android Studio 2.2 有了一个新的 ConstraintLayout,它使设计变得更加容易,但与 RelativeLayoutLinearlayout 不同,我不能使用 ScrollView 来包围 ConstraintLayout。这可能吗?如果有,怎么做?

<ScrollView 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_
        android:layout_
        tools:layout_editor_absoluteX="0dp"
        tools:layout_editor_absoluteY="0dp">
        
        <android.support.constraint.ConstraintLayout
            android:id="@+id/constraintLayout"
            android:layout_
            android:layout_
            tools:layout_editor_absoluteX="0dp"
            tools:layout_editor_absoluteY="0dp">
            
            <!-- Have whatever children you want inside -->
            
        </android.support.constraint.ConstraintLayout>
        
</ScrollView>

【问题讨论】:

是什么阻止你这样做?您总是可以直接在 XML 中添加一个... 您应该添加代码以及遇到的任何错误。 如果我使用layout_height="wrap_content",应用程序会显示一个空白屏幕,但如果我使用layout_height="match_parent",应用程序将不会滚动。 显然当将 layout_height 设置为“wrap_content”时,ConstraintLayout 会以某种方式忽略它的子元素并崩溃。即使子元素已经定义了有关 ConstraintLayout 的顶部和底部的约束(例如边距),情况也是如此。 有什么办法可以让约束布局滚动,还是我应该回去使用不同的布局? 【参考方案1】:

尝试将android:fillViewport="true" 添加到 ScrollView。

在这里找到解决方案:LinearLayout not expanding inside a ScrollView

【讨论】:

是的,这对我来说非常适合,谢谢@eric.mcgregor 你救了我的命! 即使在 Android Studio 3.0 中也可以使用!! 我的英雄走了 拯救我的一天!这应该改为接受的答案【参考方案2】:

ScrollViews 中的 ConstraintLayout 存在一个错误,该错误已得到修复。 google 已修复 Android Studio 2.2 Preview 2 (constraintlayout 1.0.0-alpha2) 中的错误。

查看此链接以获取新更新(预览版 2):works properly inside ScrollView and RecycleView

解决方案 1:

解决方案是在 ScrollView

解决方案 2:

使用NestedScrollView 代替ScrollViewandroid:fillViewport="true"

编辑 - 09/16/20:

目前,更常用的是使用ConstraintLayout高度设置为wrap_content的ScrollView,效果很好,别忘了fillViewPort,而且Scroll和Nested都只支持一个直接子级。

【讨论】:

看来他们没有修复它。它在生产版本中仍然不起作用 可以确认。即使在 2.3.3 中也没有修复。 解决方案见下文。 在 ScrollView 上添加 android:fillViewport="true" 有效。 Android Studio 4.0.1 它还在工作,谢谢! :) 但是,尽管父 ScrollView 具有 match_parent 并且子 ConstraintLayout 也具有 match_parent 属性,但为什么它会这样工作?设置match_parent时,ScrollView默认填充视口不应该是合乎逻辑的吗?【参考方案3】:

NestedScrollView 与视口一起使用对我来说效果很好

<android.support.v4.widget.NestedScrollView
        android:layout_
        android:layout_
        android:fillViewport="true">

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

        </android.support.constraint.ConstraintLayout>

</android.support.v4.widget.NestedScrollView>

【讨论】:

您,先生,拯救了我的一天。这应该是公认的答案。 为什么你给了硬编码的布局高度?,这对于 match_parent 或 wrap_content 是不可能的?【参考方案4】:

不要忘记,如果您将某些视图的底部约束到约束布局的底部。Scrollview 无法滚动。

【讨论】:

确实我有点面临这个问题:我将最后一个视图的底部限制为某个值,但 Constaintlayout 不能滚动到最后一个项目之外 在这种情况下删除底部约束并以编程方式设置minHeight。至少适用于我的用例【参考方案5】:

ScrollView layout_height 设置为wrap_content 然后它将正常工作。以下是可能对某人有所帮助的示例。 我使用compile 'com.android.support.constraint:constraint-layout:1.0.2' 进行约束布局。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    android:orientation="vertical"
    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_
    android:layout_
    android:id="@+id/activity_main"
    tools:context=".ScrollViewActivity">

    <ScrollView
        android:layout_
        android:layout_
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        >

        <android.support.constraint.ConstraintLayout 
            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_
            android:layout_
            android:orientation="vertical"
            android:paddingLeft="8dp"
            android:paddingRight="8dp"
            android:scrollbars="vertical">

            <TextView
                android:id="@+id/tvCommonSurname"
                android:layout_
                android:layout_
                android:text="surname"
                android:textAppearance="?android:attr/textAppearanceLarge"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                tools:layout_constraintLeft_creator="1"
                tools:layout_constraintTop_creator="1" />

            <EditText
                android:id="@+id/editText3"
                android:layout_
                android:layout_
                android:layout_marginTop="8dp"
                android:ems="10"
                android:inputType="text"
                android:maxLines="1"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tvCommonSurname"
                tools:layout_constraintLeft_creator="1"
                tools:layout_constraintRight_creator="1"
                tools:layout_constraintTop_creator="1" />

            <TextView
                android:id="@+id/tvCommonName"
                android:layout_
                android:layout_
                android:layout_marginTop="8dp"
                android:text="firstName"
                android:textAppearance="?android:attr/textAppearanceLarge"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/editText3"
                tools:layout_constraintLeft_creator="1"
                tools:layout_constraintTop_creator="1" />

            <EditText
                android:id="@+id/editText"
                android:layout_
                android:layout_
                android:layout_marginTop="8dp"
                android:ems="10"
                android:inputType="text"
                android:maxLines="1"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tvCommonName"
                tools:layout_constraintLeft_creator="1"
                tools:layout_constraintRight_creator="1"
                tools:layout_constraintTop_creator="1" />

            <TextView
                android:id="@+id/tvCommonLastName"
                android:layout_
                android:layout_
                android:layout_marginTop="8dp"
                android:text="middleName"
                android:textAppearance="?android:attr/textAppearanceLarge"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/editText"
                tools:layout_constraintLeft_creator="1"
                tools:layout_constraintTop_creator="1" />

            <EditText
                android:id="@+id/editText2"
                android:layout_
                android:layout_
                android:layout_marginTop="8dp"
                android:ems="10"
                android:inputType="text"
                android:maxLines="1"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tvCommonLastName"
                tools:layout_constraintLeft_creator="1"
                tools:layout_constraintRight_creator="1"
                tools:layout_constraintTop_creator="1" />

            <TextView
                android:id="@+id/tvCommonPhone"
                android:layout_
                android:layout_
                android:layout_marginTop="8dp"
                android:text="Phone number"
                android:textAppearance="?android:attr/textAppearanceLarge"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/editText2"
                tools:layout_constraintLeft_creator="1"
                tools:layout_constraintTop_creator="1" />

            <EditText
                android:id="@+id/editText4"
                android:layout_
                android:layout_
                android:layout_marginTop="8dp"
                android:digits="0123456789"
                android:ems="10"
                android:inputType="phone"
                android:maxLength="10"
                android:maxLines="1"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tvCommonPhone"
                tools:layout_constraintLeft_creator="1"
                tools:layout_constraintRight_creator="1"
                tools:layout_constraintTop_creator="1" />

            <TextView
                android:id="@+id/textView3"
                android:layout_
                android:layout_
                android:layout_marginTop="8dp"
                android:text="sex"
                android:textAppearance="?android:attr/textAppearanceLarge"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/editText4"
                tools:layout_constraintLeft_creator="1"
                tools:layout_constraintTop_creator="1" />

            <RadioGroup 
                xmlns:android="http://schemas.android.com/apk/res/android"
                android:id="@+id/radiogroup"
                android:layout_
                android:layout_
                android:layout_marginTop="8dp"
                android:orientation="horizontal"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/textView3"
                tools:layout_constraintLeft_creator="1"
                tools:layout_constraintTop_creator="1">

                <RadioButton
                    android:layout_
                    android:layout_
                    android:text="pirates" />

                <RadioButton
                    android:layout_
                    android:layout_
                    android:text="ninjas" />
            </RadioGroup>

            <TextView
                android:id="@+id/tvCommonDOB"
                android:layout_
                android:layout_
                android:layout_marginTop="8dp"
                android:text="dob"
                android:textAppearance="?android:attr/textAppearanceLarge"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/radiogroup"
                tools:layout_constraintLeft_creator="1"
                tools:layout_constraintTop_creator="1" />

            <EditText
                android:id="@+id/editText5"
                android:layout_
                android:layout_
                android:layout_marginTop="8dp"
                android:ems="10"
                android:inputType="date"
                android:maxLines="1"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tvCommonDOB"
                tools:layout_constraintLeft_creator="1"
                tools:layout_constraintRight_creator="1"
                tools:layout_constraintTop_creator="1" />

            <TextView
                android:id="@+id/tvCommonLivingCity"
                android:layout_
                android:layout_
                android:layout_marginTop="8dp"
                android:text="livingCity"
                android:textAppearance="?android:attr/textAppearanceLarge"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/editText5"
                tools:layout_constraintLeft_creator="1"
                tools:layout_constraintTop_creator="1" />

            <EditText
                android:id="@+id/editText34"
                android:layout_
                android:layout_
                android:layout_marginTop="8dp"
                android:ems="10"
                android:inputType="text"
                android:maxLines="1"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tvCommonLivingCity"
                tools:layout_constraintLeft_creator="1"
                tools:layout_constraintRight_creator="1"
                tools:layout_constraintTop_creator="1" />

            <TextView
                android:id="@+id/tvCommonPlaceOfBithday"
                android:layout_
                android:layout_
                android:layout_marginTop="8dp"
                android:text="placeOfBirth"
                android:textAppearance="?android:attr/textAppearanceLarge"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/editText34"
                tools:layout_constraintLeft_creator="1"
                tools:layout_constraintTop_creator="1" />

            <EditText
                android:id="@+id/editText6"
                android:layout_
                android:layout_
                android:layout_marginTop="8dp"
                android:ems="10"
                android:inputType="text"
                android:maxLines="1"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tvCommonPlaceOfBithday"
                tools:layout_constraintLeft_creator="1"
                tools:layout_constraintRight_creator="1"
                tools:layout_constraintTop_creator="1" />

            <TextView
                android:id="@+id/textView4"
                android:layout_
                android:layout_
                android:layout_marginTop="8dp"
                android:text="education"
                android:textAppearance="?android:attr/textAppearanceLarge"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/editText6"
                tools:layout_constraintLeft_creator="1"
                tools:layout_constraintTop_creator="1" />

            <Spinner
                android:id="@+id/spinner_id"
                android:layout_
                android:layout_
                android:layout_marginTop="8dp"
                android:spinnerMode="dialog"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/textView4"
                tools:layout_constraintLeft_creator="1"
                tools:layout_constraintRight_creator="1"
                tools:layout_constraintTop_creator="1" />

        </android.support.constraint.ConstraintLayout>
    </ScrollView>


</android.support.constraint.ConstraintLayout>

【讨论】:

为什么在ScrollView内外都有ConstraintLayout? ScrollView 应该是内部带有 ConstraintLayout 的根元素吗?【参考方案6】:

尝试为您的约束布局添加一些 padding bottom,如下所示

    <ScrollView
        android:layout_
        android:layout_
        android:layout_below="@+id/top"
        android:fillViewport="true">

        <android.support.constraint.ConstraintLayout
            android:layout_
            android:layout_
            android:paddingBottom="100dp">
        </android.support.constraint.ConstraintLayout>

    </ScrollView>

【讨论】:

【参考方案7】:

将以下属性设置为的任何人

ScrollView:android:fillViewport="true"

约束布局: android:layout_height="wrap_content"

它仍然无法正常工作,然后确保您没有将内部可滚动布局 (RecycleView) 底部约束设置为父级底部。

添加以下代码行:

android:nestedScrollingEnabled="false"
android:layout_

确保删除以下约束:

app:layout_constraintBottom_toBottomOf="parent"

完整代码

   <androidx.core.widget.NestedScrollView
    android:layout_
    android:layout_
    android:fillViewport="true">

<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/selectHubLayout"
    android:layout_
    android:layout_
    tools:context=".ui.hubs.SelectHubFragment">

    <include
        android:id="@+id/include"
        layout="@layout/signup_hub_selection_details"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_HubSelection"
        android:layout_
        android:layout_
        android:layout_marginTop="8dp"
        android:nestedScrollingEnabled="false"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/include" />
</androidx.constraintlayout.widget.ConstraintLayout>

【讨论】:

我的问题是 app:layout_constraintBottom_toBottomOf="parent" 。因此,如果您想居中,请使用 app:layout_constraintBottom_toTopOf="parent"app:layout_constraintTop_toBottomOf="parent"【参考方案8】:

由于实际的ScrollView 被封装在CoordinatorLayoutToolbar ...

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_>

    <android.support.design.widget.AppBarLayout
        android:layout_
        android:layout_
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:layout_
            android:layout_
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay"/>

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/list"/>

</android.support.design.widget.CoordinatorLayout>

...我必须定义android:layout_marginTop="?attr/actionBarSize" 才能使滚动工作:

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_
    android:layout_marginTop="?attr/actionBarSize">

    <android.support.constraint.ConstraintLayout
        android:layout_
        android:layout_
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <!-- UI elements here -->

    </android.support.constraint.ConstraintLayout>

</ScrollView>

以上也适用于NestedScrollView,而不是ScrollView。 我不需要定义android:fillViewport="true"

【讨论】:

【参考方案9】:

我花了 2 天时间尝试在所谓的“稳定”版本 Android Studio 2.2 中将布局转换为 ConstraintLayout,但我没有 ScrollView 在设计器中工作。我不打算开始在 XML 中为Views 添加约束的路线,这些约束在滚动的下方。毕竟这应该是一个视觉设计工具。

我遇到的渲染错误、堆栈溢出和主题问题的数量使我得出结论,整个ConstraintLayout 实现仍然充满了错误。除非您正在开发简单的布局,否则我会先不管它,直到它至少有更多的迭代。

那两天我不会回来了。

【讨论】:

越来越好了,一定要用最新的版本,目前是1.0.0-alpha9和File->"Invalidate Caches / Restart"。 谢谢。这是一个改进。它减少了渲染错误的数量。但我仍然不太相信它足够稳定,可以让我尝试转换我的所有布局。我决定等到他们完全摆脱“alpha”标签并发布适当的生产版本【参考方案10】:

NestedScrollViewandroid:fillViewport="true" 一起使用

<android.support.v4.widget.NestedScrollView
    android:layout_
    android:layout_
    android:fillViewport="true">

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

        <!--Edit your stuff-->

    </android.support.constraint.ConstraintLayout>

</android.support.v4.widget.NestedScrollView>

【讨论】:

【参考方案11】:

我在 ConstraintLayout 中有 NestedScrollView,而这个 NestedScrollView 有一个 ConstraintLayout

如果您遇到NestedScrollView 的问题,

android:fillViewport="true"添加到 NestedScrollView,成功了。

【讨论】:

【参考方案12】:

问题:

当我想在另一个布局中包含 ConstraintLayout 和ScrollView 时遇到问题。

决定:

我的问题的解决方案是使用 dataBinding。

dataBinding (layout)

【讨论】:

【参考方案13】:

不要忘记ScrollView 中的tools:context=".YouClassName" 属性。

这是导致我的应用程序崩溃的原因。

【讨论】:

以上是关于是否可以将 ConstraintLayout 放在 ScrollView 中?的主要内容,如果未能解决你的问题,请参考以下文章

使用ConstraintLayout将水平回收视图放置在特定位置

一文看懂ConstraintLayout的用法

ios中的障碍,如android ConstraintLayout

是否建议在 Android 的 ConstraintLayout 中使用 LinearLayout?

ConstraintLayout:如何展平此布局?

ConstraintLayout:第二个视图捕捉到父视图而不是自定义视图的底部