ConstraintLayout和RelativeLayout之间的区别

281

ConstraintLayoutRelativeLayout有什么区别?


12
ConstraintLayout 主要是为新手程序员设计的,以便他们可以使用可视化编辑器轻松设计布局,而不是通过 XML 手动构建布局。原文已经表达清楚,我只需将其翻译成通俗易懂的中文即可。 - CopsOnRoad
1
@Jack,对于经验丰富的开发人员来说,它肯定也有更深层次的目的。 - Moses Aprico
@MosesAprico,你说得对,确实有这个功能。但我认为经验丰富的开发人员已经知道了很多其他方法(例如RealtiveLayoutLinearLayoutGridLayout等)来获取他们想要的视图层次结构。 - CopsOnRoad
11
@CopsOnRoad,你其实错了。苹果已经使用约五年的约束布局技术。它可以让你的设计在任何尺寸下都能很好地呈现,并且不需要编写大量复杂的布局代码。当你需要绑定多个视图时,只需要使用三个基本控件就可以创建完全响应式的设计。 - Nick Turner
10个回答

181

ConstraintLayout 的意图是通过对每个视图应用一些规则来优化和扁平化布局的视图层次结构,以避免嵌套。

这些规则与 RelativeLayout 类似,例如将底部边缘设置为另一个视图的底部。

app:layout_constraintBottom_toBottomOf="@+id/view1"
RelativeLayout不同,ConstraintLayout 提供了一个bias值,该值用于以相对于手柄(用红色圆圈标记)的0%和100%水平和垂直偏移来定位视图。这些百分比(和分数)提供了在不同屏幕密度和大小之间无缝定位视图的功能。
app:layout_constraintHorizontal_bias="0.33" <!-- from 0.0 to 1.0 -->
app:layout_constraintVertical_bias="0.53" <!-- from 0.0 to 1.0 -->
基准线柄(一个带有圆角的长管,位于圆形柄下方)用于将视图内容与另一个视图参考对齐。 每个角落上的正方形柄用于以dp为单位调整视图大小。 enter image description here 这完全是基于个人意见和我对ConstraintLayout的印象。

11
我们仍然可以使用RelativeLayout创建平面布局,所以我不明白ConstraintLayout在哪些方面超越了RelativeLayout?请注意,翻译过程中要确保内容准确无误、表达清晰易懂,但不得添加解释或其他额外信息。 - user6685522
8
RelativeLayout 是一个双重布局,会遭受重复计算的困扰。它必须至少测量/布局两次。相比之下,ConstraintLayout 不会有这种性能惩罚。 - Christopher Perry
5
是的,我们仍然可以使用RelativeLayout创建平面布局。但除了这里提到的所有内容外,ConstraintLayout还允许您使用负边距预定义比例中的大小子视图。最后一种方法是根据Material Design保持卡片视图中ImageView的16:9比率最强大的方式。 - Eugene Brusov
4
除非您将LinearLayout或另一个RelativeLayout嵌套在其中,否则在RelativeLayout中有一些布局是不可能实现的。例如:将一个由3个视图组成的“堆栈”在垂直方向上相对于另一个视图居中。 - Gak2
似乎你可以使用ConstraintLayout几乎做任何事情,无需其他东西的需要? - CodeMonkey
显示剩余2条评论

137

相对布局和约束布局等效属性

Relative Layout and Constraint Layout equivalent properties

(1) 相对布局:

android:layout_centerInParent="true"    

(1) 约束布局的等效方式:

app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"

(2) 相对布局:

android:layout_centerHorizontal="true"

(2) 约束布局的等效方式:

app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintEnd_toEndOf="parent"

(3) 相对布局:

android:layout_centerVertical="true"    

(3) 约束布局等效:

app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"

(4) 相对布局:

android:layout_alignParentLeft="true"   

(4) 约束布局相当于:

app:layout_constraintLeft_toLeftOf="parent"

(5) 相对布局:

android:layout_alignParentStart="true"

(5) 约束布局等效:

app:layout_constraintStart_toStartOf="parent"

(6) 相对布局:

android:layout_alignParentRight="true"

(6) 约束布局等效:

app:layout_constraintRight_toRightOf="parent"
(7) 相对布局:
android:layout_alignParentEnd="true"    

(7) 约束布局等效:

app:layout_constraintEnd_toEndOf="parent"

(8) 相对布局:

android:layout_alignParentTop="true"

(8) 约束布局的等效替代:

app:layout_constraintTop_toTopOf="parent"
(9) 相对布局:
android:layout_alignParentBottom="true" 

(9) Constraint Layout相当于:

app:layout_constraintBottom_toBottomOf="parent"

(10) 相对布局:

android:layout_alignStart="@id/view"

(10) 约束布局等效:

app:layout_constraintStart_toStartOf="@id/view"
(11) 相对布局:
android:layout_alignLeft="@id/view" 

(11) Constraint Layout 相当于:

app:layout_constraintLeft_toLeftOf="@id/view"

(12) 相对布局:

android:layout_alignEnd="@id/view"  

(12) 约束布局等效:

app:layout_constraintEnd_toEndOf="@id/view"

(13) 相对布局:

android:layout_alignRight="@id/view"

(13) Constraint Layout 相当于:

app:layout_constraintRight_toRightOf="@id/view"

(14) 相对布局:

android:layout_alignTop="@id/view"  

(14) Constraint Layout 等效布局:

app:layout_constraintTop_toTopOf="@id/view"
相对布局:
android:layout_alignBaseline="@id/view" 

(15) 约束布局等效:

app:layout_constraintBaseline_toBaselineOf="@id/view"

(16) 相对布局:

android:layout_alignBottom="@id/view"

(16) 约束布局的等效实现:

app:layout_constraintBottom_toBottomOf="@id/view"
相对布局:
android:layout_toStartOf="@id/view"

(17) 约束布局等效方法:

app:layout_constraintEnd_toStartOf="@id/view"

(18) 相对布局:

android:layout_toLeftOf="@id/view"  

(18) 约束布局的等效形式:

app:layout_constraintRight_toLeftOf="@id/view"

(19) 相对布局:

android:layout_toEndOf="@id/view"

(19) 约束布局等效方法:

app:layout_constraintStart_toEndOf="@id/view"

(20) 相对布局:

android:layout_toRightOf="@id/view"

(20) 约束布局的等效实现:

app:layout_constraintLeft_toRightOf="@id/view"
(21) 相对布局:
android:layout_above="@id/view" 

(21) 约束布局的等效实现:

app:layout_constraintBottom_toTopOf="@id/view"

(22) 相对布局:

android:layout_below="@id/view" 

(22) 约束布局的等效实现:

app:layout_constraintTop_toBottomOf="@id/view"


4
你能否以文本形式发布,而不是图片?这样对我和其他人在未来都会非常有用。 - Vijayadhas Chandrasekaran
10
每个开始学习 Constraint Layout 的人都需要看到这个。谢谢。 - grantespo
2
这是有用的信息,但只是一堆文档转储,并没有解释它们之间的区别。 - YetAnotherRandomUser
5
不,我没有时间查看文档,这肯定很有用。而且用简单的语言写的。点赞。 - CodeToLife

55

@davidpbr 报告了 ConstraintLayout 的性能问题。

我创建了两个相似的有7个子视图的布局,一个是父布局为ConstraintLayout,另一个是RelativeLayout

根据Android Studio中的方法跟踪工具显示,ConstraintLayout 在onMeasure中花费更多时间,并在onFinishInflate中执行额外的工作。

使用的库(support-v4appcompat-v7…):

com.android.support.constraint:constraint-layout:1.0.0-alpha1

复现的设备/Android版本: 三星Galaxy S6 (SM-G920A。抱歉,目前没有Nexus)。 Android 5.0.2

快速方法跟踪比较:

1

示例Github代码库:https://github.com/OnlyInAmerica/ConstraintLayoutPerf


2
@Nativ Monitors->CPU->时间跟踪器图标 - Andrey T
22
在Nexus 5上安装Android 6.0.1系统,使用constraint-layout:1.0.1版本运行并测试同一段代码,以下是测试结果: 相对布局(Relative layout)- 初始化时间为2毫秒 测量时间为30毫秒+16毫秒=62毫秒 布局时间为7毫秒=9毫秒 总计54毫秒约束布局(Constraint Layout)- 初始化时间为7毫秒 约束布局生成布局参数以及添加视图的时间约为7*2毫秒=14毫秒 测量时间为60毫秒+52毫秒≈112毫秒 布局时间为8毫秒 总计约141毫秒 相对布局的首次初始化速度几乎是约束布局的三倍。 - Andrey T
@JacktheRipper:谷歌说约束更快。请参见https://dev59.com/aloU5IYBdhLWcg3wk3l2#47289870 - serv-inc
4
引入Constraint Layout的目的是为了减少嵌套视图层次结构,这样可以减少从视图树顶部向下遍历所需的时间。因此,在Constraint布局中不需要使用可能不必要的嵌套视图层次结构,相比之下,使用相对布局更容易出现嵌套结构,这是什么意思呢? - codepeaker
1
这是有价值的信息,但并没有回答问题。甚至也没有涉及到问题。 - YetAnotherRandomUser
显示剩余4条评论

43
以下是区别/优势:
  1. 约束布局具有相对布局和线性布局的双重功能:设置视图的相对位置(如相对布局),还可以为动态 UI 设置权重(这在线性布局中是唯一可能的)。

  2. 一个非常强大的用途是通过形成链来分组元素。这样,我们可以形成一组视图,这些视图作为一个整体可以以所需的方式放置,而不必添加另一层层次结构来形成另一组视图。

  3. 除了权重之外,我们还可以应用水平和垂直偏差,这只是距离中心的百分比。(偏差为0.5表示居中对齐。任何较小或较大的值都意味着在相应方向上进行相应的移动)。

  4. 另一个非常重要的功能是,它尊重并提供处理 GONE 视图的功能,以便如果通过 Java 代码将某个视图设置为 GONE,则布局不会中断。更多信息请参见: https://developer.android.com/reference/android/support/constraint/ConstraintLayout.html#VisibilityBehavior

  5. 通过使用蓝图和可视化编辑器工具提供自动约束应用的功能,这使得设计页面变得容易。

所有这些功能都导致视图层次结构的扁平化,从而提高了性能,并有助于创建响应式和动态 UI,可以更轻松地适应不同的屏幕大小和密度。

这是快速学习的最佳场所: https://codelabs.developers.google.com/codelabs/constraint-layout/#0


1
  1. ConstraintLayout 让我们可以按照预定义比例对子视图进行大小调整。https://medium.com/google-developers/building-interfaces-with-constraintlayout-3958fa38a9f7。例如,当您需要将 ImageView 保持在 16:9 时,它会非常有用。
- Eugene Brusov

26
一个重要的区别是 ConstraintLayout 在视图消失时仍然会遵守约束条件,因此如果你有一个链条并且想让中间的某个视图消失,它不会破坏布局。

1
你能给我一个例子吗?假设有3个按钮。我将隐藏第二个按钮,第三个按钮附加到第二个按钮上,其ID为btn2。假设我隐藏了第二个按钮,那么第三个按钮如何找到第二个按钮的ID? - user6685522
2
这不是真的。如果你将一个按钮的可见性设置为“INVISIBLE”而不是“GONE”,你不会破坏约束条件。对我来说,正如@Nikola所说的最大区别是偏差,它可以帮助你创建更“响应”的视图。 - zapotec
假设这些按钮是相互垂直排列的。即使你隐藏了tButton 2,它仍然存在于“view contract”中,无论是在xml还是代码中。ConstraintLayout会尊重它,并且Button 3将位于Button 1下方。在RelativeLayout中,Button 2消失了,约束也随之消失,因此Button 3将处于默认位置,即屏幕左上角。 - Herrbert74
@zapotec 我尊重你认为其他东西更重要,但对我来说,这是一个非常酷的不同之处。解决了我在RelativeLayout中唯一讨厌的事情。使用invisible不是一个选项,因为它会占用空间。 - Herrbert74

9

官方声明中,ConstraintLayout的性能比RelativeLayout要快得多。

在Android的N版本中,ConstraintLayout类提供了与RelativeLayout类似的功能,但成本显著降低。


8
我可以得出的结论是:
1)我们可以在不触及代码的xml部分的情况下进行UI设计。说实话,我感觉谷歌复制了iOS应用程序中的UI设计方式。如果您熟悉iOS中的UI开发,这将是有意义的,但是在相对布局中,如果不触及xml设计,则很难设置约束。
2)其次,它具有扁平的视图层次结构,不像其他布局,因此比相对布局具有更好的性能,您可能已经从其他答案中看到了。
3)它还具有相对布局没有的额外功能,例如圆形相对定位,在这种情况下,我们可以以特定半径和特定角度相对于另一个视图定位此视图,而在相对布局中无法实现。
我再次强调,使用约束布局设计UI与在iOS中设计UI相同,因此,如果您使用过约束布局,则在未来在iOS上工作时会更容易。

7
实际上值得问的问题是,除了约束布局外,是否有使用其他布局的理由?我认为答案可能是否定的。对于那些坚称它们面向初学者程序员或类似人群的人来说,他们应该提供一些理由来证明它们不如其他布局。约束布局在各个方面都更好(它们确实会增加APK大小约150k)。它们更快、更容易、更灵活、对变化反应更快,当项目消失时它们能够很好地解决问题,它们更符合完全不同的屏幕类型,并且它们不使用一堆嵌套循环和那种长长的树形结构来处理所有事情。你可以把任何东西放在任何地方,相对于任何东西,放在任何地方。在2016年中期它们有点混乱,可视化布局编辑器还不够好,但现在它们已经到了这样的程度,如果你要使用布局,你可能需要认真考虑使用约束布局,即使它做的是与RelativeLayout甚至简单的LinearLayout相同的事情。FrameLayout显然仍然有它们的用途。但是,我目前看不到建立任何其他东西的必要性。如果他们从这个开始,他们就不会添加任何其他东西了。

2
有没有证明它更快的证据? - Rajesh N
1
是的。它更快。布局在单个求解器中完成,而不是通过树进行迭代。对于大多数事情来说,这并不重要,因为它在调用布局时完成。但是,视图树虽然易于使用,但会创建一堆需要调用的视图内部视图。尽管从理论上讲更好,但实际上,在一个代码块中执行布局比遍历整个视图树要容易得多。随着视图数量的增加,它将变得更令人印象深刻,但以下是5月份的基准测试:https://medium.com/@krpiotrek/constraintlayout-performance-c1455c7984d7 - Tatarize
我面临另一个问题,我应该替换我正在开发的应用中的所有现有相对布局吗?这样做会显著提高性能吗? - Sreekanth Karumanaghat
@SreekanthKarumanaghat,看起来你永远无法节省回替换所需的时间。我们说的是从3.5毫秒循环降到大多数情况下的3.25毫秒。如果它给你额外的功能或你需要的东西,那当然可以,但纯粹基于速度考虑不行。虽然我们在谈论点击转换按钮的问题。 - Tatarize

7
除了 @dhaval-jivani 的回答之外。
我已经将项目 github 更新到最新版本的约束布局 v.1.1.0-beta3。
我测量并比较了 onCreate 方法的时间以及从 onCreate 开始到最后一个可在 CPU 监视器中看到的 preformDraw 方法执行结束的时间。所有测试都在安卓 6.0.1 上的三星 S5 mini 上完成。以下是结果:
首次启动(应用程序启动后第一次打开的屏幕)
相对布局
OnCreate:123ms
最后一个 preformDraw 时间 - OnCreate 时间:311.3ms
约束布局
OnCreate:120.3ms
最后一个 preformDraw 时间 - OnCreate 时间:310ms
除此之外,我已经查看了来自这个 文章代码 的性能测试,并发现在循环次数少于100的情况下,使用约束布局变体在填充、测量和布局执行期间比相对布局变体更快。而且在像三星S3这样的旧安卓设备上差距更大。
综上所述,我同意 文章 中的评论。

这是否值得将旧视图从RelativeLayout或LinearLayout转换为其上的重构?

一如既往:这取决于具体情况。

除非当前布局层次存在性能问题或您想要进行重大更改,否则我不会重构任何内容。尽管我最近没有进行过测量,但在最近的版本中,我没有发现任何性能问题。因此,我认为您可以放心使用它。但是-正如我所说的-不要只是为了迁移而迁移。只有在需要以及从中获益时才这样做。 不过,对于新布局,我几乎总是使用ConstraintLayout。与之前的设计相比,它要好得多。


1
我所注意到的唯一区别是,通过拖放设置相对布局的元素会自动推断其尺寸与其他元素的关系,因此当您运行应用程序时,您看到的就是您得到的。然而,在约束布局中,即使您在设计视图中拖放一个元素,当您运行应用程序时,事情可能会被移动。这可以通过手动设置约束来轻松解决,或者更冒险的方法是右键单击组件树中的元素,选择约束布局子菜单,然后单击“推断约束”。希望这有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接