Jetpack Compose | Modifier常用修饰符的使用(一)

Modifier修饰符

Compose提供了Column、Row、Box 三种布局组件,其中Column/Row 对应 View体系中LinearLayout的 Vertical/Horizontal 方向,Box相当于 FrameLayout,而借助Modifier修饰符,可以修饰或扩充布局组件。通常使用修饰符来执行以下操作:

  • 更改可组合项的大小、布局、行为和外观
  • 添加信息,如无障碍标签
  • 处理用户输入
  • 添加高级互动,如使元素可点击、可滚动、可拖动或可缩放

Modifier 以链式调用的方式来设置组件的样式,每个UI 组件都会有一个modifier参数,通过传入该参数来改变组件。

常用修饰符

列举一些常用的Modifier 修饰符:

  • Modifier.width(width: Dp)
  • Modifier.height(height: Dp)
  • Modifier.size(width: Dp, height: Dp)

设置具体的宽高,单位是dp, 如设置宽度500dp,高度100dp:

kotlin 复制代码
.width(500.dp).height(100.dp)
//或者直接在size里设置宽高
//.size(width = 500.dp, height = 100.dp)

如果子布局中有 requiredSize,那么requiredSize的优先级更高一些,如果希望尺寸固定不变,而不考虑传入的约束条件,请使用 requiredSize 修饰符。

  • Modifier.fillMaxWidth(fraction: Float = 1f) :子布局填充父项允许的所有可用宽度
  • Modifier.fillMaxHeight(fraction: Float = 1f) :子布局填充父项允许的所有可用高度
  • Modifier.fillMaxSize(fraction: Float = 1f) :子布局填充父项允许的所有可用宽高

让内容填充(可能仅部分填充)传入的测量约束的最大宽高,其中fraction 取值范围是[0.0, 1.0],默认是1.0。

  • Modifier.background(color: Color, shape: Shape = RectangleShape)

设置背景,如果想设置渐变色的背景,可以通过Brush的方式添加,如下:

kotlin 复制代码
 Modifier.background(brush: Brush,
         shape: Shape = RectangleShape,
         /*@FloatRange(from = 0.0, to = 1.0)*/
         alpha: Float = 1.0f
) 

使用:

kotlin 复制代码
val bgGradient = Brush.verticalGradient(
      colors = listOf(Color.Red, Color.Green, Color.Yellow, Color.Cyan))
//设置渐变色
Row(modifier = Modifier.background(bgGradient)){
   ...
}
  • Modifier.border(border: BorderStroke, shape: Shape)
  • Modifier.border(width: Dp, color: Color, shape: Shape)
  • Modifier.border(width: Dp, brush: Brush, shape: Shape)

修改元素,指定外观的边框 ,边框可以指定颜色、粗细、Shape形状等,并进行裁剪。

  • Modifier.padding(all: Dp)
  • Modifier.padding(horizontal: Dp, vertical: Dp)
  • Modifier.padding(start: Dp, top: Dp, end: Dp, bottom: Dp)

设置内外边距,传统的View 体系中有padding和margin的区分,而在Compose中只有一个padding修饰符,根据不同的位置可以表示内、外边距。可以简单理解为:padding在元素的"外部"应用外边距,而在元素的"内部"应用内边距。

  • Modifier.offset(x: Dp = 0.dp, y: Dp = 0.dp)

offset 用来偏移内容,可以直接传入x y,单位是dp,也可以使用offset的重载方法,返回一个IntOffset,两种写法是等价的:

kotlin 复制代码
//1
Modifier.offset(x = 100.dp, y = 100.dp)
//2
Modifier.offset {IntOffset(100.dp.roundToPx(), 100.dp.roundToPx())}

offset 可以是正数,也可以是负数。offset 修饰符根据布局方向水平应用。从左到右布局时,右移为正;反之从右到左布局时,左移为正。如果不考虑布局方向,可以使用 absoluteOffset 修饰符,不管如何布局,会强制向右布局。

kotlin 复制代码
//3 absoluteOffset强制从左向右移动
Modifier.absoluteOffset(x = 100.dp, y = 100.dp)
//4
Modifier.absoluteOffset {IntOffset(100.dp.roundToPx(), 100.dp.roundToPx())}
  • Modifier.align(alignment: Alignment) :在Box的子控件中使用,表示将内容拉取到Box中的特定Alignment位置。Alignment 的取值有:TopStart、TopCenter、TopEnd、CenterStart、Center、CenterEnd、BottomStart、BottomCenter、BottomEnd
  • Modifier.align(alignment: Alignment.Vertical) :在Row的子控件中使用,表示在Row 中垂直对齐元素。Alignment.Vertical 的取值有:Top、CenterVertically、Bottom
  • Modifier.align(alignment: Alignment.Horizontal) :在Column 的子控件中使用,表示在Column 中水平对齐元素。Alignment.Horizontal 的取值有:Start、CenterHorizontally、End

更多Modifier修饰符的用法参见:Modifier修饰符列表:https://developer.android.com/jetpack/compose/modifiers-list?hl=zh-cn

作用域限定

某些Modifier修饰符只能应用于某些可组合项的子项,Compose 通过自定义作用域强制实施此安全机制。

matchParentSize(作用于Box中)

在Box中,如果希望某个子项与父项 Box 同样大,而不影响 Box 尺寸,可以使用 matchParentSize 修饰符。

matchParentSize 仅适用于Box的子控件中,可以保证当前组件的尺寸与父组件相同,父组件如果未设置宽高默认是wrapContent;而如果改为使用fillMaxSize,则会被设置为父组件所允许的最大尺寸。示例如下:

kotlin 复制代码
@Composable
private fun BoxSample() {
   Box {
       Spacer(modifier = Modifier.matchParentSize().background(Color.Yellow))
       Text(text = "Jetpack Compose", modifier = Modifier.padding(10.dp))
    }
}

执行结果:

上述代码中,如果将matchParentSize改为fillMaxSize,则执行结果为:

weight(作用于Column 和 Row 中)

weight只能在Column 和 Row 中使用,跟View体系中LinearLayout中的weight是一个概念。示例如下:

kotlin 复制代码
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) {
        //设置渐变色
        val bgGradient = Brush.verticalGradient(
            colors = listOf(Color.Red, Color.Green, Color.Yellow, Color.Cyan)
        )
        Row(
            modifier = Modifier
                .background(bgGradient)
                .fillMaxWidth()
                .height(40.dp),
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Text(
                text = "Tab1",
                modifier = Modifier.weight(1f), //1
                textAlign = TextAlign.Center,
            )
            Image(
                modifier = Modifier
                    .wrapContentSize(align = Alignment.BottomCenter, true)
                    .weight(1f) //2
                    .clip(CircleShape)
                    .border(width = 2.dp, Color.Red, CircleShape)
                    .requiredSize(80.dp),
                painter = painterResource(id = R.drawable.icon_cat_w),
                contentScale = ContentScale.Crop,
                contentDescription = ""
            )
            Text(
                text = "Tab2",
                modifier = Modifier.weight(1f), //3
                textAlign = TextAlign.Center,
            )
        }
    }

Row中的子控件通过在1、2、3处设置weight 来均分横向宽度,执行结果:

上述示例中是一个综合示例,不仅使用了weight修饰符,还是用的clip、border等,最终展示是三个均分的底部Tab控件,其中图片大小不受父控件的约束(通过requiredSize实现的)。

注意修饰符顺序

修饰符函数的顺序非常重要。因为每个Modifier 修饰符函数都会对上一个函数返回的 Modifier 进行更改,因此顺序会影响最终结果。如:

kotlin 复制代码
Box(
    modifier = Modifier
            .size(200.dp, 100.dp)
            .background(Color.Gray)
            .padding(20.dp)
            .border(1.dp, Color.Red, RectangleShape)
            .padding(20.dp)
            .background(Color.Green)
   )

对于border而言,在其前面的设置padding 可以认为是外边距,在其后面设置的 padding可以认为是内边距。通过修饰符的前后顺序可以控制内外边距,这也说明了为什么没有外边距修饰符,而只有 padding 修饰符。

相关推荐
雨白2 小时前
Android 多线程:理解 Handler 与 Looper 机制
android
sweetying4 小时前
30了,人生按部就班
android·程序员
用户2018792831675 小时前
Binder驱动缓冲区的工作机制答疑
android
真夜5 小时前
关于rngh手势与Slider组件手势与事件冲突解决问题记录
android·javascript·app
用户2018792831675 小时前
浅析Binder通信的三种调用方式
android
用户095 小时前
深入了解 Android 16KB内存页面
android·kotlin
火车叼位6 小时前
Android Studio与命令行Gradle表现不一致问题分析
android
前行的小黑炭8 小时前
【Android】 Context使用不当,存在内存泄漏,语言不生效等等
android·kotlin·app
前行的小黑炭9 小时前
【Android】CoordinatorLayout详解;实现一个交互动画的效果(上滑隐藏,下滑出现);附例子
android·kotlin·app
用户20187928316721 小时前
Android黑夜白天模式切换原理分析
android