原文: Jetpack Compose学习(6)——关于Modifier的妙用 | Stars-One的杂货小窝

之前学习记录中也是陆陆续续地将常用的Modifier的方法穿插进去了,本期就来详细的讲解下关于modifier的使用

限于篇幅,我是以常用的属性来讲解,漏讲了一些请见谅,毕竟方法真的太多了,之后可能有用的新的效果,会穿插地讲些

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

基本使用

我们直接以个简单的例子讲解下使用,设置Box布局的宽高各100dp,且内边距为16dp,背景色为绿色,代码如下

Column {
Box(
Modifier
.size(100.dp)
.background(Color.Green)
.padding(16.dp)
)
Box(
Modifier
.size(100.dp)
.padding(16.dp)
.background(Color.Green)
)
}

由上面代码和效果可以看到,modifier中的顺序不同会导致效果不同,这是因为Modifier的设计如此

如果我们先设置背景色,之后再设置padding,那么padding也是在绿色背景的基础上进行的,所以,就是图中全是绿色的效果

如果是先设置padding,那么我们设置背景色是针对里面的布局进行设置,而不会讲padding也算到里面去

宽高类和边距

首先,先是讲解常用的属性,设置宽高和边距

size

同时设置宽高

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

width

单独设置宽度

  • width(intrinsicSize: IntrinsicSize) 这个参数是自定义布局测量里的,本篇暂时不讲解
  • width(width: Dp)

hegiht

单独设置高度

  • hegiht(intrinsicSize: IntrinsicSize) 这个参数是自定义布局测量里的,本篇暂时不讲解
  • hegiht(hegiht: Dp)

defaultMinSize

设置宽高的默认最小值

defaultMinSize(
minWidth: Dp = Dp.Unspecified,
minHeight: Dp = Dp.Unspecified
):

sizeIn

设置宽高的最小值和最大值,宽度在minWidth~maxWidth之间,高度在minHeight~maxHeight之间

sizeIn(
minWidth: Dp = Dp.Unspecified,
minHeight: Dp = Dp.Unspecified,
maxWidth: Dp = Dp.Unspecified,
maxHeight: Dp = Dp.Unspecified
):

同理,也有单独给宽度或高度设置的方法

  • widthIn(min: Dp = Dp.Unspecified, max: Dp = Dp.Unspecified)
  • heightIn(min: Dp = Dp.Unspecified, max: Dp = Dp.Unspecified)

fillMaxSize

宽高都填充满父布局(相当于原生xml中的match_parent)

fillMaxSize(fraction: Float = 1f)

默认是1f,代表填充满父布局,如果设置为0.5f,则是填满父布局的0.5(即一半)

除此之外,也有单独给宽度或高度方法

= fillMaxWidth(fraction: Float = 1f)

= fillMaxHegiht(fraction: Float = 1f)

wrapContentSize

组件的控件宽高若是小与定义的最小宽高,会将组件进行排列的设置

wrapContentSize(
align: Alignment = Alignment.Center,
unbounded: Boolean = false
)

上面说的可能不是太好懂,以一个例子来说明吧

Box(
Modifier.sizeIn(minWidth = 40.dp, minHeight = 40.dp)
.wrapContentSize(Alignment.TopCenter)
.size(20.dp)
.background(Color.Blue)
)

我们设置了Box的组件的最小宽高为40dp,但此Box的宽高实际设置成了20dp,如果没有加上这个方法wrapContentSize,那么最终渲染出的Box宽高其实是40dp x 40dp,且是蓝色背景

而由于我们加上了这个方法,最终渲染出的Box宽高就为20dp x 20dp,且排列对齐方式会按照wrapContentSize中的align参数进行

同理,也有单独设置宽度或高度的方法

wrapContentHeight(
align: Alignment.Vertical = Alignment.CenterVertically,
unbounded: Boolean = false
) //使用例子
Box(
Modifier.size(50.dp)
.wrapContentHeight(Alignment.CenterVertically)
.height(20.dp)
.background(Color.Blue)
)
wrapContentWidth(
align: Alignment.Horizontal = Alignment.CenterHorizontally,
unbounded: Boolean = false
) //使用例子
Box(
Modifier.size(50.dp)
.wrapContentWidth(Alignment.CenterHorizontally)
.width(20.dp)
.background(Color.Blue)
)

padding

有四种不同的参数,各位看着用就行,之前文章中也是有详细讲解,这里不再赘述

padding(all: Dp)

点击事件类(点击 双击 长按)

clickable

给任意组件(包括布局)设置点击事件,且自带点击水波纹效果

clickable(
enabled: Boolean = true,
onClickLabel: String? = null,
role: Role? = null,
onClick: () -> Unit
)

onClickLabelrole主要是为残疾人(应该是盲人)设置的属性,可以不用设置

此外,还有另外的参数列表

clickable(
interactionSource: MutableInteractionSource,
indication: Indication?,
enabled: Boolean = true,
onClickLabel: String? = null,
role: Role? = null,
onClick: () -> Unit
)

interactionSource之前也有讲过,是用来判断按钮的点击状态,具体可以看之前讲解关于Button的使用的文章

indication看文档说明是说用来绘制水波纹或者点击高亮的效果,具体使用没有深究,下面给个例子:

val interactionSource = remember { MutableInteractionSource() }
Column {
Text(
text = "Click me and my neighbour will indicate as well!",
modifier = Modifier
// clickable will dispatch events using MutableInteractionSource and show ripple
.clickable(
interactionSource = interactionSource,
indication = rememberRipple()
) {
/**do something */
}
.padding(10.dp)
)
Spacer(Modifier.requiredHeight(10.dp))
Text(
text = "I'm neighbour and I indicate when you click the other one",
modifier = Modifier
// this element doesn't have a click, but will show default indication from the
// CompositionLocal as it accepts the same MutableInteractionSource
.indication(interactionSource, LocalIndication.current)
.padding(10.dp)
)
}

效果如下图所示

combinedClickable

组合点击事件,可以给组件点击,双击,长按监听操作

不过,需要注意的是,此方法是实验性方法,也不知道后面版本更新会有所改变

combinedClickable(
enabled: Boolean = true,
onClickLabel: String? = null,
role: Role? = null,
onLongClickLabel: String? = null,
onLongClick: () -> Unit = null,
onDoubleClick: () -> Unit = null,
onClick: () -> Unit
)

看方法很好理解,onLongClick是长按操作,onDoubleClick是双击操作,onClick是点击操作

val context = LocalContext.current
Box(
Modifier
.size(50.dp)
.background(Color.Blue)
.combinedClickable(onLongClick = {
Toast.makeText(context, "长按操作", Toast.LENGTH_SHORT).show()
}, onDoubleClick = {
Toast.makeText(context, "双击操作", Toast.LENGTH_SHORT).show()
}, onClick = {
Toast.makeText(context, "点击操作", Toast.LENGTH_SHORT).show()
})
)

形状(shape) 边框(border) 背景(background)

border

设置边框宽度和形状

border(border: BorderStroke, shape: Shape = RectangleShape)
border(width: Dp, color: Color, shape: Shape = RectangleShape))
border(width: Dp, brush: Brush, shape: Shape)

Brush是设置渐变,如下面的例子

//红蓝绿三色水平渐变
val gradientBrush = Brush.horizontalGradient(
colors = listOf(Color.Red, Color.Blue, Color.Green),
startX = 0.0f,
endX = 500.0f,
tileMode = TileMode.Repeated
)
Text(
"Text with gradient border",
modifier = Modifier.padding(10.dp).border(width = 2.dp, brush = gradientBrush, shape = CircleShape)
.padding(10.dp)
)

效果如下:

后期再出一篇讲解Brush的使用

background

设置背景及背景形状

background(color: Color, shape: Shape = RectangleShape)
background(brush: Brush, shape: Shape = RectangleShape,alpha: Float = 1.0f)

alpha是设置透明度

background有两种参数列表,具体使用也是与上面的类似,这里不过多赘述

阴影

shadow(elevation: Dp, shape: Shape = RectangleShape, clip: Boolean)

滚动效果

之前在讲解布局的时候有提及,Row和Column布局里面的子组件,宽高若是大于父组件就是导致子组件被隐藏,我们可以将其设置为滚动效果

但Compose没有Scrollview,要想Row或Column实现滚动效果,就得使用modifier来实现

verticalScroll

horizontalScroll(
state: ScrollState,
enabled: Boolean = true,
flingBehavior: FlingBehavior? = null,
reverseScrolling: Boolean = false
)

flingBehavior这个参数不是很理解做什么用的..

Column(Modifier.verticalScroll(rememberScrollState())) {
repeat(10){
Box(
Modifier
.fillMaxWidth()
.height(200.dp)
){
Text(text = "测试$it")
}
}
}

效果如下:

如果不加上verticalScroll,Column是无法向下滚动的

reverseScrolling设置为true的话,默认自动滚动到底部,效果如下所示

Column一般和verticalScroll连用实现垂直方向的滚动效果,而Row则与horizontalScroll连用

horizontalScroll

horizontalScroll(
state: ScrollState,
enabled: Boolean = true,
flingBehavior: FlingBehavior? = null,
reverseScrolling: Boolean = false
)

使用与上面的类似,这里不再赘述

scrollable

scrollable(
state: ScrollableState,
orientation: Orientation,
enabled: Boolean = true,
reverseDirection: Boolean = false,
flingBehavior: FlingBehavior? = null,
interactionSource: MutableInteractionSource? = null
)

没太搞懂这个主要是实现什么效果的..

文档的示例代码:

// actual composable state that we will show on UI and update in `Scrollable`
val offset = remember { mutableStateOf(0f) }
Box(
Modifier
.size(150.dp)
.scrollable(
orientation = Orientation.Vertical,
// state for Scrollable, describes how consume scroll amount
state = rememberScrollableState { delta ->
offset.value = offset.value + delta // update the state
delta // indicate that we consumed all the pixels available
}
)
.background(Color.LightGray),
contentAlignment = Alignment.Center
) {
Text(offset.value.roundToInt().toString(), style = TextStyle(fontSize = 32.sp))
}

效果

选择

selectable

可用来实现单选功能

val option1 = Color.Red
val option2 = Color.Blue
var selectedOption by remember { mutableStateOf(option1) }
Column {
Text("Selected: $selectedOption")
Row {
listOf(option1, option2).forEach { color ->
val selected = selectedOption == color
Box(
Modifier
.size(100.dp)
.background(color = color)
.selectable(
selected = selected,
onClick = { selectedOption = color }
)
){
if(selected) Text(text = "已选",color = Color.White)
}
}
}
}

效果:

toggleable

类似复选框的勾选及不勾选

var checked by remember { mutableStateOf(false) }
// content that you want to make toggleable
Text(
modifier = Modifier.toggleable(value = checked, onValueChange = { checked = it }),
text = checked.toString()
)

效果如下:

变化类(旋转 缩放 放大)

aspectRatio

Box(Modifier.width(100.dp).aspectRatio(2f).background(Color.Green))

rotate

组件沿中心顺时针旋转,最高支持360°

//顺时针旋转45°
Box(
Modifier.rotate(45f)
.size(100.dp, 100.dp)
)

效果如下:

scale

缩放或放大

Box(
Modifier.scale(scaleX = 0.2f, scaleY = 0.5f)
.background(Color.Black)
.size(100.dp, 100.dp)
)

不过看实际效果,感觉是将宽和高都往中间缩放了

参考

Jetpack Compose学习(6)——关于Modifier的妙用的更多相关文章

  1. Jetpack Compose学习(9)——Compose中的列表控件(LazyRow和LazyColumn)

    原文:Jetpack Compose学习(9)--Compose中的列表控件(LazyRow和LazyColumn) - Stars-One的杂货小窝 经过前面的学习,大致上已掌握了compose的基 ...

  2. Jetpack Compose学习(2)——文本(Text)的使用

    原文: Jetpack Compose学习(2)--文本(Text)的使用 | Stars-One的杂货小窝 对于开发来说,文字最为基础的组件,我们先从这两个使用开始吧 本篇涉及到Kotlin和DSL ...

  3. Jetpack Compose学习(3)——图标(Icon) 按钮(Button) 输入框(TextField) 的使用

    原文地址: Jetpack Compose学习(3)--图标(Icon) 按钮(Button) 输入框(TextField) 的使用 | Stars-One的杂货小窝 本篇分别对常用的组件:图标(Ic ...

  4. Jetpack Compose学习(4)——Image(图片)使用及Coil图片异步加载库使用

    原文地址 Jetpack Compose学习(4)--Image(图片)使用及Coil图片异步加载库使用 | Stars-One的杂货小窝 本篇讲解下关于Image的使用及使用Coil开源库异步加载网 ...

  5. Jetpack Compose学习(5)——从登录页美化开始学习布局组件使用

    原文:Jetpack Compose学习(5)--从登录页美化开始学习布局组件使用 | Stars-One的杂货小窝 本篇主要讲解常用的布局,会与原生Android的布局控件进行对比说明,请确保了解A ...

  6. Jetpack Compose学习(7)——MD样式架构组件Scaffold及导航底部菜单

    Jetpack Compose学习(7)--MD样式架构组件Scaffold及导航底部菜单 | Stars-One的杂货小窝 Compose给我们提供了一个Material Design样式的首页组件 ...

  7. Jetpack Compose学习(8)——State及remeber

    原文地址: Jetpack Compose学习(8)--State状态及remeber关键字 - Stars-One的杂货小窝 之前我们使用TextField,使用到了两个关键字remember和mu ...

  8. Jetpack Compose学习(1)——从登录页开始入门

    原文地址:Jetpack Compose学习(1)--从登录页开始入门 | Stars-One的杂货小窝 Jetpack Compose UI在前几天出了1.0正式版,之前一直还在观望,终于是出了正式 ...

  9. Jetpack Compose 1.0 终于要投入使用了!

    前言 Jetpack Compose 是用于构建原生界面的「新款 Android 工具包」.2021 Google IO 大会上,Google宣布:「Jetpack Compose 1.0 即将面世」 ...

随机推荐

  1. Spring详解(八)------常用的连接池配置

    首先,我们准备Jdbc属性文件 jdbc.properties,用于保存连接数据库的信息,利于我们在配置文件中的使用 jdbc.driver=com.mysql.jdbc.Driver jdbc.ur ...

  2. 三 MongoDB进阶

    1 Limit方法 概念:查询指定数量的数据,该方法接受一个数字参数作为查询记录数的数量 举个例子:查询集合col中最多2条记录数 2 Skip方法 概念:查询到的结果集中,跳过指定数量的数据,该方法 ...

  3. 【CSS复合选择器、元素显示模式、背景】前端小抄(3) - Pink老师自学笔记

    [CSS复合选择器.元素显示模式.背景]前端小抄(3) 本学习笔记是个人对 Pink 老师课程的总结归纳,转载请注明出处! 一.CSS的复合选择器 1.1 什么是复合选择器 在 CSS 中,可以根据选 ...

  4. jwt三种方式

    package library.book.demo.config.loginconfig; import com.alibaba.fastjson.JSON; import com.sun.org.a ...

  5. spring动态切换数据源(一)

    介绍下spring数据源连接的源码类:| 1 spring动态切换连接池需要类AbstractRoutingDataSource的源码 2 /* 3 * Copyright 2002-2017 the ...

  6. 两种github action 打包.Net Core 项目docker镜像推送到阿里云镜像仓库

    两种github action 打包.Net Core 项目docker镜像推送到阿里云镜像仓库 1.GitHub Actions 是什么? 大家知道,持续集成由很多操作组成,比如抓取代码.运行测试. ...

  7. How to check type of files without extensions in python? 不通过文件扩展名,怎样知道文件类型?

    有一个命令 file 可以用 $ file fuck fuck.png: PNG image data, 1122 x 750, 8-bit colormap, non-interlaced pyth ...

  8. (1)RabbitMQ在Docker上安装

    1.简介 在来学习RabbitMQ时候,我觉得很有必要先把它的环境先搭建起来,这样后面的示例才能进行.因为之前自己手动在Linux服务器上搭建过Elasticsearch,当时踩过太多坑了,浪费太多时 ...

  9. AFL++ Fuzz一个libexif例子

    CVE-2009-3895 首先在NVD找到漏洞描述如下: 大致意思是说:libexif 0.6.18 中的 libexif/exif-entry.c 中的 exif_entry_fix 函数中基于堆 ...

  10. (3)java Spring Cloud+Spring boot+mybatis企业快速开发架构之SpringCloud-Spring Cloud和Dubbo的区别及各自的优缺点

    ​ 我们先从 Nginx 说起,了解为什么需要微服务.最初的服务化解决方案是给相同服务提供一个统一的域名,然后服务调用者向这个域发送 HTTP 请求,由 Nginx 负责请求的分发和跳转. 这种架构存 ...