是否可以将 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,它使设计变得更加容易,但与 RelativeLayout
和 Linearlayout
不同,我不能使用 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
代替ScrollView
和android: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
被封装在CoordinatorLayout
和Toolbar
...
<?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】:将NestedScrollView
与android: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将水平回收视图放置在特定位置
ios中的障碍,如android ConstraintLayout