ConstraintLayout约束布局使用全解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ConstraintLayout约束布局使用全解相关的知识,希望对你有一定的参考价值。


文章目录

  • ​​目的​​
  • ​​居中​​
  • ​​居中于⽗容器​​
  • ​​居中于控件中⼼​​
  • ​​⽔平⽅向居中​​
  • ​​垂直⽅向居中​​
  • ​​居中于控件的边​​
  • ​​填充​​
  • ​​权重​​
  • ​​⽂字基准线对⻬​​
  • ​​圆形定位​​
  • ​​特殊属性​​
  • ​​约束限制​​
  • ​​偏向​​
  • ​​约束链​​
  • ​​宽⾼⽐​​
  • ​​百分⽐布局​​
  • ​​辅助控件**GuideLine**​​
  • ​​Group​​
  • ​​Layer​​
  • ​​Barrier​​
  • ​​ConstraintHelper​​
  • ​​Placeholder​​
  • ​​**Flow**​​
  • ​​自定义一个简单linearLayout​​
  • ​​ConstraintSet​​
  • ​​布局扁平化更加容易做过渡动画​​

目的

为何:布局扁平化,减少布局层级,即提高性能;

约束布局 默认需要一个垂直方向和水平方向的约束;

约束布局中的宽高的0dp含义:充满约束

宽高:match_constraint:充满父容器约束

居中

居中于⽗容器

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

居中于控件中⼼

⽔平⽅向居中

app:layout_constraintStart_toStartOf="@id/view"
app:layout_constraintEnd_toEndOf="@id/view"

垂直⽅向居中

app:layout_constraintTop_toTopOf="@id/view"
app:layout_constraintBottom_toBottomOf="@id/view"

居中于控件的边

控件垂直居中于 view 的「下边」

app:layout_constraintTop_toBottomOf="@id/view"
app:layout_constraintBottom_toBottomOf="@id/view"

填充

⽔平⽅向填充⽗容器(通过 ​​match_constraint​​ )

app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_

备注:在早期版本中 match_parent 没有效果。

权重

为⽔平⽅向的控件设置权重,⼤⼩为 2:1:1 。

<!-- (view-1) -->
android:layout_
app:layout_constraintHorizontal_weight="2"

<!-- (view-2) -->
android:layout_
app:layout_constraintHorizontal_weight="1"

<!-- (view-3) -->
android:layout_
app:layout_constraintHorizontal_weight="1"

⽂字基准线对⻬

app:layout_constraintBaseline_toBaselineOf

圆形定位

通过「圆⼼」「⻆度」「半径」设置圆形定位

app:layout_constraintCircle="@id/view"
app:layout_constraintCircleAngle="90"
app:layout_constraintCircleRadius="180dp"

特殊属性

约束限制

限制控件⼤⼩不会超过约束范围。

app:layout_constrainedWidth="true"
app:layout_constrainedHeight="true

偏向

控制控件在垂直⽅向的 30%的位置

app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintVertical_bias="0.3"

除了配合百分⽐定位,还有⽤于配合有时在「约束限制」的条件下不需要居中效果

的情况

垂直⽅向居顶部

app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constrainedHeight="true"
app:layout_constraintVertical_bias="0.0"

约束链

在约束链上的第⼀个控件上加上 ​​chainStyle​​ ,⽤来改变⼀组控件的布局⽅式

  • packed(打包)
  • spread (扩散)
  • spread_inside(内部扩散)

垂直⽅向 packed

app:layout_constraintVertical_chainStyle="packed"

宽⾼⽐

  • ⾄少需要⼀个⽅向的值为 ​​match_constraint​
  • 默认的都是「宽⾼⽐」,然后根据另外⼀条边和⽐例算出match_constraint 的值

宽高比,宽高都是0dp,即充满父约束指定高是计算出来的:

android:layout_height = "0dp"
android:layout_width = "0dp"
app:layout_constraintDimensionRatio = "H,2:1"

百分⽐布局

-需要对应⽅向上的值为 match_constraint

-百分⽐是 parent 的百分⽐,⽽不是约束区域的百分⽐

宽度是⽗容器的 30%

android:layout_
app:layout_constraintWidth_percent="0.3"

辅助控件GuideLine

  • 设置辅助线的⽅向 android:orientation=“vertical”
  • 设置辅助线的位置,根据⽅向不同:

距离左侧或上侧的距离 layout_constraintGuide_begin

距离右侧或下侧的距离 layout_constraintGuide_end

百分⽐ layout_constraintGuide_percent

Group

通过 constraint_referenced_ids 使⽤引⽤的⽅式来避免布局嵌套。

可以为⼀组控件统⼀设置 setVisibility

只有设置可⻅度的功能,不要指望这个来通知设置点击事件…

Layer

和 Group 类似,同样通过引⽤的⽅式来避免布局嵌套,可以为⼀组控件统⼀设置旋

转/缩放/ 位移。

Barrier

通过设置⼀组控件的某个⽅向的屏障,来 避免布局嵌套 。

<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
android: layout_
android: layout_
app: barrierDirection="end"
app: constraint_referenced_ids="viewl, view2"/>

ConstraintHelper

example:用声明写动画

import android.view.ViewAnimationUtils
import androidx.constraintlayout.widget.ConstraintHelper
import androidx.constraintlayout.widget.ConstraintLayout
import kotlin.math.hypot

class CircularRevealHelper(context: Context, attrs: AttributeSet) : ConstraintHelper(context, attrs)
override fun updatePostLayout (container: ConstraintLayout)
super.updatePostLayout (container)

referencedIds.forEach
val view = container.getViewById(it)
val radius = hypot (view.width.toDouble(), view.height.toDouble()).toInt ()
ViewAnimationUtils.createCircularReveal(view, centerX: 0, centerY: 0, startRadius: Of, radius.toFloat())
.setDuration(2000L)
.start()


<androidx.constraintlayout.widget.ConstraintLayout
...
>
...

<com.hencoder.CircularRevealHelper
android: layout _
android: layout_
app:constraint_referenced_ ids="image1, image2, image3, image4"
/>

</androidx.constraintlayout.widget.ConstraintLayout>

Placeholder

通过 setContentId 来将指定控件放到占位符的位置。

findViewById<Pfaceholder>(R.id.placeholder).setContentId(view.id)

Flow

通过引⽤的⽅式来避免布局嵌套。

wrapMode

  • chain
  • aligned
  • none(默认)

注意这个控件是可以被测量的,所以对应⽅向上的值可能需要被确定(即不能只约束同⼀⽅ 向的单个约束)

<androidx. constraintlayout.helper.widget.Flow
android: id="@+id/flow"
android: layout
android: layout_
android: layout _marginStart="16dp"
android: layout_marginTop="16dp"I
android: background="@color/colorAccent"
android:orientation="horizontal"
app: flow wrapMode="chain"
app: flow verticalGap="16dp" //竖直间距
app: flow_horizontalGap="16dp"//水平间距
app: constraint_referenced_ids="viewl, view2, view3, view4"
app: layout_constraintStart_toStartOf="parent"
app: layout_constraintTop_toTopOf="parent"/>

自定义一个简单linearLayout

class Linear (context: Context, attrs: AttributeSet) : VirtualLayout (context, attrs) 

private val constraintSet: ConstraintSet by lazy
ConstraintSet().apply this: ConstraintSet
isForceld = false


override fun updatePreLayout (container: ConstraintLayout)
super.updatePreLayout (container)
constraintSet.clone(container)

val viewIds : IntArray! = referencedIds;
for (i: Int in 1 until mCount)

val current: Int = viewIds[i]
val before : Int = viewIds[i - 1]
constraintSet. connect (current, ConstraintSet.START, before, ConstraintSet.START)
constraintSet.connect (current, ConstraintSet.TOP, before, ConstraintSet.BOTTOM)
constraintSet.applyTo(container)


ConstraintSet

使⽤ ConstraintSet 对象来动态修改布局。通过 ConstraintSet#clone 来从 xml 布局中获取约束集。

val constraintLayout = view as ConstraintLayout
val constraintSet = ConstraintSet ().apply this: ConstraintSet
clone (constraintLayout)
connect (
R.id.twitter,
ConstraintSet.BOTTOM,
ConstraintSet.PARENT_ID,
ConstraintSet.BOTTOM
)

constraintSet.applyTo(constraintLayout)

防⽌布局中有⽆ id 控件时报错,需要设置 isForceId = false

布局扁平化更加容易做过渡动画

在布局修改(constraintSet)之前加上 TransitionManager 来⾃动完成过渡动画。

constraintSet如果采用代码的方式编写,较为复杂,可以写两个xml布局,一个动画之前的,一个动画之后的,再用clone,将constraintSet吸出来,加以动画即可:

TransitionManager.beginDelayedTransition(constraintLayout)


以上是关于ConstraintLayout约束布局使用全解的主要内容,如果未能解决你的问题,请参考以下文章

ConstraintLayout 约束布局

Android 新控件之ConstraintLayout(约束布局)

Android中的ConstraintLayout约束布局

约束布局ConstraintLayout加快布局速度

Android ConstraintLayout 约束布局 Width 0dp constrainedWidth 百分比布局使用

ConstraintLayout(约束布局) part 1