一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天 点击查看活动详情。
一、修饰符---Modifier
前面我们给Text设置宽高的时候,有用到一个Modifier,我们称为修饰符。Google官方对Modifier的描述为:一个有序的、不可变的修饰元素集合,用于给Compose UI元素添加装饰或者行为,例如背景、内边距、点击事件等,或者给Text设置单行、给Button设置各种点击状态等行为。
1. 内边距 padding
如何为控件添加内边距:
Text(text = "小码农沐枫", modifier = Modifier.padding(30.dp))
很简单,只需要调用padding并传入相应的dp就行了。那我们看一看padding的源码是怎样的吧:
@Stable
fun Modifier.padding(
start: Dp = 0.dp,
top: Dp = 0.dp,
end: Dp = 0.dp,
bottom: Dp = 0.dp
)
@Stable
fun Modifier.padding(
horizontal: Dp = 0.dp,
vertical: Dp = 0.dp
)
@Stable
fun Modifier.padding(all: Dp)
我们可以看到,padding有多种设置方式,可以单独设置一边,也可以统一设置上下的或左右的,还可以设置所有的。
2. 设置控件的尺寸
在以前我们布局的时候,一般有三种设置布局大小的方法:充满父布局、自适应大小和固定大小。这三种情况放在Compose中又该如何实现呢?
1. 充满父布局
Text(text = "小码农沐枫", modifier = Modifier.fillMaxSize())
是不是很简单,但是如果我们只需要充满高或者宽呢?
Text(text = "小码农沐枫", modifier = Modifier.fillMaxHeight())
Text(text = "小码农沐枫", modifier = Modifier.fillMaxWidth())
2. 自适应大小
这种又该如何实现呢?其实更简单,就是我们什么都不加,它就是自适应大小的
3. 固定大小
如何设置固定大小的呢?这有两种写法,一种是宽高一样的情况下,一种是分别设置宽高的情况
Text(text = "小码农沐枫", modifier = Modifier.size(100.dp))
Text(text = "小码农沐枫", modifier = Modifier.size(width = 100.dp, height = 50.dp))
3. weight修饰符
说起weight,相比大家都非常熟悉了,在XML布局中,在线性布局中进行设置权重。在Compose中也是直接使用weight来设置权重。
Row(
Modifier
.fillMaxSize()
.padding(top = 20.dp)) {
Box(modifier = Modifier
.weight(1f)
.height(50.dp).background(Color.Red))
Box(modifier = Modifier
.weight(2f)
.height(50.dp).background(Color.Green))
}
我们来看一下运行效果:
4. 给控件添加点击事件
在Compose中,Modifier就可以设置点击事件:
Text(text = "小码农沐枫", modifier = Modifier.clickable {
// 执行点击操作
})
5. 给控件添加圆角
在Compose中想要为控件设置圆角的话,通过Modifier.shadow就可以实现,话不多说,先看源码:
@Stable
fun Modifier.shadow(
elevation: Dp,// 阴影的高度
shape: Shape = RectangleShape,// Shape
clip: Boolean = elevation > 0.dp// 是否将内容图形剪裁到该形状
)
@Composable
fun TestText() {
MyComposeDemoTheme{
Image(
painter = painterResource(id = R.drawable.ic_launcher_background),
contentDescription = "",
modifier = Modifier
.size(50.dp)
.shadow(elevation = 4.dp, shape = MaterialTheme.shapes.medium)
)
}
}
@Preview(showBackground = true)
@Composable
fun TestTextPreview() {
TestText()
}
看一下效果:
Compose中的EditText
在上一篇说到了Compose中的TextView --- Text,在这里我们一起去学习Compose中的EditText --- TextField。
1. 文本的输入和修改
Compose中TextField允许用户输入和修改文字。TextField的实现分为两个级别:TextField和BasicTextField。
1.TextField
先看看它是如何使用的?
@Composable
fun TestText() {
val text = remember {
mutableStateOf("你好, 沐枫")
}
Box(modifier = Modifier.size(width = 200.dp, height = 50.dp)){
TextField(
value = text.value,
onValueChange = { text.value = it },
label = { Text(text = "Label") },
)
}
}
看一下运行效果:
我们在看一下OutlinedTextField的使用:
@Composable
fun TestText() {
val text = remember {
mutableStateOf("你好, 沐枫")
}
Box(modifier = Modifier.size(width = 200.dp, height = 50.dp)){
OutlinedTextField(
value = text.value,
onValueChange = { text.value = it },
label = { Text(text = "Label") },
)
}
}
用法和TextField一样, 下面我们看一下运行效果:
2.BasicTextField
BasicTextField允许用户通过硬件键盘或软件键盘编辑文字,但是没有提供提示或占位符等装饰。用法如下:
@Composable
fun TestText() {
val text = remember {
mutableStateOf("你好, 沐枫")
}
Box(modifier = Modifier.size(width = 200.dp, height = 50.dp)){
BasicTextField(
value = text.value,
onValueChange = { text.value = it },
)
}
}
可以看到,除了不能设置label之外,它与OutlinedTextField和TextField的使用方法基本一样
2. 显示样式
话不多说,由于TextField和BasicTextField的参数基本一样,我们就以TextField为例子,先看源码:
@Composable
fun TextField(
value: String, // 显示文字
onValueChange: (String) -> Unit,// 监听用户的输入改变
modifier: Modifier = Modifier,// 修饰符
enabled: Boolean = true,// 是否可点击
readOnly: Boolean = false,// 是否只读
textStyle: TextStyle = LocalTextStyle.current,// 样式
label: @Composable (() -> Unit)? = null,// 标签
placeholder: @Composable (() -> Unit)? = null,// hint,输入为空是显示的文本
leadingIcon: @Composable (() -> Unit)? = null,// 显示在文本字段容器开头的图标
trailingIcon: @Composable (() -> Unit)? = null,// 显示在文本字段容器末尾的图标
isError: Boolean = false,// 指示文本字段的当前值是否错误
visualTransformation: VisualTransformation = VisualTransformation.None,// 转换输入value的可视表示形式
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,// 配置的软件键盘选项
keyboardActions: KeyboardActions = KeyboardActions(),// 当输入服务发出IME操作时,将调用相应的回调
singleLine: Boolean = false,// 是否单行
maxLines: Int = Int.MAX_VALUE,// 最大行数
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },// 文本字段容器的形状
shape: Shape =
MaterialTheme.shapes.small.copy(bottomEnd = ZeroCornerSize, bottomStart = ZeroCornerSize),
colors: TextFieldColors = TextFieldDefaults.textFieldColors()// 用于解析处于不同状态的该文本字段的文本颜色
)
看到注释就简单多了, 我们写个例子试试:
@Composable
fun TestText() {
val text = remember {
mutableStateOf("你好, 沐枫")
}
Box(modifier = Modifier.size(width = 200.dp, height = 50.dp)) {
TextField(
value = text.value,
onValueChange = { text.value = it },
maxLines = 2,
textStyle = TextStyle(color = Color.Red, fontWeight = FontWeight.Bold),
modifier = Modifier.padding(20.dp)
)
}
}
看一下运行效果:
3. 键盘选项
设置键盘选项用到的是TextField的keyboardOptions参数,参数类型是KeyboardOptions,类型第一次见? 先看源码:
@Immutable
class KeyboardOptions constructor(
val capitalization: KeyboardCapitalization = KeyboardCapitalization.None,
val autoCorrect: Boolean = true,
val keyboardType: KeyboardType = KeyboardType.Text,
val imeAction: ImeAction = ImeAction.Default
){
companion object {
/**
* Default [KeyboardOptions]. Please see parameter descriptions for default values.
*/
val Default = KeyboardOptions()
}
}
1. capitalization
capitalization参数的类型为KeyboardCapitalization, 先看源码
inline class KeyboardCapitalization internal constructor(internal val value: Int) {
companion object {
// 不自动大写文本
val None = KeyboardCapitalization(0)
// 所有字符大写
val Characters = KeyboardCapitalization(1)
// 每个单词首字母大写
val Words = KeyboardCapitalization(2)
// 每个句子的首字母大写
val Sentences = KeyboardCapitalization(3)
}
}
2. autoCorrect
autoCorrect参数:通知键盘是否启用自动更正,autoCorrect仅适用于基于文本的KeyboardType,例如Email、Uri,它不会应用于Number
3.keyboardType
keyboardType参数的类型为KeyboardType,用于设置键盘类型:
inline class KeyboardType internal constructor(@Suppress("unused") private val value: Int) {
companion object {
// 用于请求显示常规键盘的IME的键盘类型
val Text: KeyboardType = KeyboardType(1)
// 用于请求能够输入ASCII字符
val Ascii: KeyboardType = KeyboardType(2)
// 输入数字
val Number: KeyboardType = KeyboardType(3)
// 输入电话号码
val Phone: KeyboardType = KeyboardType(4)
// 输入URI
val Uri: KeyboardType = KeyboardType(5)
// 输入电子邮件底子
val Email: KeyboardType = KeyboardType(6)
// 输入密码
val Password: KeyboardType = KeyboardType(7)
// 输入数字密码
val NumberPassword: KeyboardType = KeyboardType(8)
}
}
4. imeAction
imeAction的参数类型是ImeAction, 键盘的回车的类型,先看源码:
inline class ImeAction internal constructor(@Suppress("unused") private val value: Int) {
companion object {
// 使用平台和键盘默认设置
val Default: ImeAction = ImeAction(1)
// 不执行任何操作, 默认是换行
val None: ImeAction = ImeAction(0)
// 转到输入中文本目标, 访问Uri
val Go: ImeAction = ImeAction(2)
// 搜索
val Search: ImeAction = ImeAction(3)
// 发送
val Send: ImeAction = ImeAction(4)
// 返回到先前的输入
val Previous: ImeAction = ImeAction(5)
// 移至表单的下一个字段,
val Next: ImeAction = ImeAction(6)
// 输入完成操作
val Done: ImeAction = ImeAction(7)
}
}
举个栗子:
Box(modifier = Modifier.size(width = 200.dp, height = 50.dp)) {
TextField(
value = text.value,
onValueChange = { text.value = it },
maxLines = 2,
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.Characters, // 设置全部大写
keyboardType = KeyboardType.Email,
autoCorrect = true,
imeAction = ImeAction.Search
),
textStyle = TextStyle(color = Color.Red, fontWeight = FontWeight.Bold),
modifier = Modifier.padding(20.dp)
)
}
看一下运行效果:
5. 监听imeAction并执行
前面我们把IME的动作设置为Search,但是我们点击搜索按钮是没有效果的,因为我们还没有设置相应的交互。设置交互我们用到的是TextField中的keyboardActions参数,参数类型是KeyboardActions, 先看源码:
class KeyboardActions(
val onDone: (KeyboardActionScope.() -> Unit)? = null,
val onGo: (KeyboardActionScope.() -> Unit)? = null,
val onNext: (KeyboardActionScope.() -> Unit)? = null,
val onPrevious: (KeyboardActionScope.() -> Unit)? = null,
val onSearch: (KeyboardActionScope.() -> Unit)? = null,
val onSend: (KeyboardActionScope.() -> Unit)? = null
) {
companion object {
val Default: KeyboardActions = KeyboardActions()
}
}
我们修改一下上面的例子:
val context = LocalContext.current
val text = remember {
mutableStateOf("你好, 沐枫")
}
Box(modifier = Modifier.size(width = 200.dp, height = 50.dp)) {
TextField(
value = text.value,
onValueChange = { text.value = it },
maxLines = 2,
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.Characters, // 设置全部大写
keyboardType = KeyboardType.Email,
autoCorrect = true,
imeAction = ImeAction.Search
),
keyboardActions = KeyboardActions(
onSearch = {
Toast.makeText(context, "搜索: ${text.value}", Toast.LENGTH_SHORT).show()
}
),
textStyle = TextStyle(color = Color.Red, fontWeight = FontWeight.Bold),
modifier = Modifier.padding(20.dp)
)
}
查看运行结果:
最后
感谢你看到最后, 最后再说两点~
①如果你持有不同的看法,欢迎你在文章下方进行留言、评论。
②如果对你有帮助,或者你认可的话,欢迎给个小点赞,支持一下~
我是沐小枫,一个热爱学习、热爱编程的山东人
(文章内容仅供学习参考, 如有侵权,非常抱歉,请立即联系作者删除。)