Jetpack Compose学习(14)——ConstraintLayout约束布局使用

原文地址: Jetpack Compose学习(14)——ConstraintLayout约束布局使用-Stars-One的杂货小窝

本文阅读之前,需要了解ConstraintLayout的使用!

各位可查阅我的ConstraintLayout使用一文

本系列以往文章请查看此分类链接Jetpack compose学习

引入依赖

implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0") 

可在下方链接查看官方的最新版本

Constraintlayout | Jetpack | Android Developers

简单示例

在compose里的约束布局,需要先通过createRef()方法创建ref对象,之后通过Modifier.constrainAs()来进行对应的约束对齐,如下简单例子:

2个组件,图片和文本,文本与图片的top和bottom对齐,位于图片的右侧,间距16dp

注意: createRef(),createRefs(),Modifier.constrainAs()这个ConstraintLayoutScope作用域才能使用!下面的其他的方法也是如此,之后不再赘述!

ConstraintLayout(modifier= Modifier 	.fillMaxWidth() 	.height(100.dp) 	.background(Color.Blue)) {//这里是ConstraintLayoutScope作用域 	 	//createRef 	//val portraitImageRef = remember { 	//    createRef() 	//} 	//val userNameTextRef = remember { 	//    createRef() 	//}  	//这个可以快速创建多个引用(但一次最多只能支持16个变量!) 	val (portraitImageRef,userNameTextRef) = remember{ createRefs()}  	Image(painter = painterResource(id = R.drawable.ic_auto), contentDescription =null ,modifier=Modifier.size(50.dp).constrainAs(portraitImageRef){ 		top.linkTo(parent.top) 		start.linkTo(parent.start) 		bottom.linkTo(parent.bottom) 	})  	Text("myname",modifier=Modifier.constrainAs(userNameTextRef){ 		top.linkTo(portraitImageRef.top) 		//还可以设置margin和goneMargin,这里我只设置了margin属性 		start.linkTo(portraitImageRef.end, margin = 16.dp) 		bottom.linkTo(portraitImageRef.bottom) 	})  } 

constrainAs的函数体中,我们还可以设置当前组件的width和height属性,具体有下面几个选项

Dimension Type Description
wrapContent() 实际尺寸为根据内容自适应的尺寸
matchParent() 实际尺寸为铺满整父组件的尺寸
fillToConstraints() 实际尺寸为根据约束信息拉伸后的尺寸
preferredWrapContent() 如果剩余空间大于根据内容自适应的尺寸时,实际尺寸为自适应的尺寸。如果剩余空间小于内容自适应的尺寸时,实际尺寸则为剩余空间的尺寸。
ratio (String) 根据字符串计算实际尺寸所占比率,例如 "1:2"
percent (Float) 根据浮点数计算实际尺寸所占比率
value (Dp) 将尺寸设置为固定值
preferredValue (Dp) 如果剩余空间大于固定值时,实际尺寸为固定值。如果剩余空间小于固定值时,实际尺寸则为剩余空间的尺寸。

一个简单示例(某个组件占满剩余宽度):

Jetpack Compose学习(14)——ConstraintLayout约束布局使用

ConstraintLayout(modifier= Modifier 	.fillMaxWidth() 	.height(100.dp) 	.background(Color.Blue)) { 	  	val (tv1Ref,tv2Ref) = remember{ createRefs()}  	Text("一个字",modifier=Modifier.constrainAs(tv1Ref){ 		top.linkTo(parent.top) 		start.linkTo(parent.start) 	}) 	  	Text("右侧文本内容",modifier=Modifier.constrainAs(tv2Ref){ 		start.linkTo(tv1Ref.end) 		end.linkTo(parent.end) 		//占满剩余空间,实际等同于普通约束布局中,给width属性设置为0dp 		width = Dimension.fillToConstraints 	}.background(Color.Yellow)) } 

除了上面几个start.linkTo,还有基线的对齐

baseline.linkTo(parent.baseline) 

动态更改约束条件

除了上面说到的createRef方法,我们还可以通过Modifier.layoutId(id)createRefFor(id)来联用进行创建ref对象

ConstraintSet对象就表明了当前的布局里的各组件的对齐关系,我们只需要构造ConstraintLayout的时候,传递此对象即可达到动态更新约束条件的效果!

下面是一个简单的示例:

private fun decoupledConstraints(margin: Dp): ConstraintSet {     return ConstraintSet {         val button = createRefFor("button")         val text = createRefFor("text")          constrain(button) {             top.linkTo(parent.top, margin = margin)         }         constrain(text) {             top.linkTo(button.bottom, margin)         }     } }  @Composable fun SettingPage(modifier: Modifier = Modifier) {     val constraints = decoupledConstraints(margin = 32.dp)      ConstraintLayout(constraints) {         Button(             onClick = { /* Do something */ }, modifier = Modifier.layoutId("button")         ) {             Text("Button")         }          Text("Text", Modifier.layoutId("text"))     } } 

Barrier

平时在约束布局,不是很常用这个,一般用的GuideLine多些,不过也是记录下

这个需要依托存在的组件才能创建

ConstraintLayout{ 	val (tv1Ref,tv2Ref,iv1Ref) = remember{ createRefs()} 	//创建位于组件右边的一个屏障 	val barrier = createEndBarrier(tv1Ref,tv2Ref) 	 	Text("一个字",modifier=Modifier.constrainAs(tv1Ref){ 		top.linkTo(parent.top) 		start.linkTo(parent.start) 	}) 	 	Text("十四个字",modifier=Modifier.constrainAs(tv2Ref){ 		top.linkTo(tv1Ref.bottom) 		start.linkTo(tv1Ref.start) 	}) 	 	//image始终位于2个文本的最右边(以最长文本为准) 	Image(painter = painterResource(id = R.drawable.ic_auto), contentDescription =null,modifier=Modifier.size(50.dp).constrainAs(iv1Ref){ 		start.linkTo(barrier) 	} ) } 

Jetpack Compose学习(14)——ConstraintLayout约束布局使用

createEndBarrier方法即在组件的右边位置创建屏障,除此之外还有其他3个方向的

  • createStartBarrier()
  • createTopBarrier()
  • createBottomBarrier()

GuideLine

引导线可以通过createGuidelineFromTop()方法直接创建,个人一般用此来进行百分比宽度等划分,然后让组件占满

于上面一样,还有其他方向,这里就不补充了,就是换个名字,代码提示直接可以搜到了

方法可接受一个0-1f范围之间的百分比或者固定的偏移量dp,如下面例子:

val guide = createGuidelineFromTop(0.2f) val guide = createGuidelineFromTop(20.dp) 

一个完整使用示例:

Jetpack Compose学习(14)——ConstraintLayout约束布局使用

ConstraintLayout(modifier= Modifier         .fillMaxSize()         .background(Color.Blue)) {          val (tv2Ref) = remember { createRefs() }                  val guide = createGuidelineFromTop(0.2f)          Text("底下占满",modifier= Modifier             .constrainAs(tv2Ref) {                 top.linkTo(guide)                 bottom.linkTo(parent.bottom)                 width = Dimension.matchParent                 height = Dimension.fillToConstraints             }             .background(Color.Yellow))     } 

Chain

熟悉约束布局使用都知道这个了,有水平或垂直2种,然后ChainStyle类型有3种,这里不赘述了

  • createVerticalChain()
  • createHorizontalChain()
createVerticalChain(imageOneRef, imageTwoRef, chainStyle = ChainStyle.Spread) 

参考

发表评论

评论已关闭。

相关文章