@Composable fun Text( text: String, modifier: Modifier = Modifier, //修饰符 color: Color = Color.Unspecified, fontSize: TextUnit = TextUnit.Unspecified, fontStyle: FontStyle? = null, fontWeight: FontWeight? = null, fontFamily: FontFamily? = null, letterSpacing: TextUnit = TextUnit.Unspecified, textDecoration: TextDecoration? = null, textAlign: TextAlign? = null, lineHeight: TextUnit = TextUnit.Unspecified, overflow: TextOverflow = TextOverflow.Clip, softWrap: Boolean = true, maxLines: Int = Int.MAX_VALUE, onTextLayout: (TextLayoutResult) -> Unit = {}, style: TextStyle = LocalTextStyle.current )
Text
是 Compose
中最基本的布局组件,它可以显示文字
@Composable fun TextDemo() { Text("Hello World") }
从 res
中加载文字
@Composable fun TextDemo() { Text(stringResource(id = R.string.content)) } examples 桃之夭夭,灼灼其华。之子于归,宜其室家。
style
参数可以帮助我们配置文本的行高,颜色,粗体等设置
Compose` 中内置的 `theme` 已经为我们准备了一些设计, 从 `h1` 到 `overline @Composable fun TextDemo() { Column{ Text( text = "你好呀陌生人,这是一个标题", style = MaterialTheme.typography.h6 ) Text( text ="你好呀陌生人,我是内容", style = MaterialTheme.typography.body2 ) } }
文字间距
@Composable fun TextDemo() { Column( modifier = Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { Text( text = "你好陌生人", style = TextStyle( fontWeight = FontWeight.W900, //设置字体粗细 fontSize = 20.sp, letterSpacing = 7.sp ) ) } }
使用 maxLines
参数可以帮助我们将文本限制在指定的行数之间,如果文本足够短则不会生效,如果文本超过 maxLines
所规定的行数,则会进行截断
@Composable fun TextDemo() { Column{ Text( text = "你好呀陌生人,这是一个标题,不是很长,因为我想不出其他什么比较好的标题了", style = MaterialTheme.typography.h6, maxLines = 1, ) Text( text ="你好呀陌生人,我是内容", style = MaterialTheme.typography.body2 ) } }
overflow 处理溢出
使用 overflow
参数可以帮助我们处理溢出的视觉效果
@Composable fun TextDemo() { Column{ Text( text = "你好呀陌生人,这是一个标题,不是很长,因为我想不出其他什么比较好的标题了", style = MaterialTheme.typography.h6, maxLines = 1, overflow = TextOverflow.Ellipsis ) Text( text ="你好呀陌生人,我是内容", style = MaterialTheme.typography.body2 ) } }
当我们在 Text
中设置了 fillMaxWidth()
之后,我们可以指定 Text
的对齐方式
@Composable fun TextDemo() { Column { Text( text = "每天摸鱼", modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Left ) Text( text = "这好吗", modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center ) Text( text = "这非常的好", modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Right ) } }
注意
需要注意区分的是,TextAlign
设置的是文本的对齐方式,而不是位置方向
使用 lineHeight 参数可以让我们指定 Text
中每行的行高间距
Column { Text( text = "两面包夹芝士".repeat(15), ) Spacer(Modifier.padding(vertical = 15.dp)) Text( text = "两面包夹芝士".repeat(15), lineHeight = 30.sp ) }
使用 fontFamily
参数可以让我们自定义字体,它的调用方法是这样的:
Column { Text("Hello World", fontFamily = FontFamily.Serif) Text("Hello World", fontFamily = FontFamily.SansSerif) }
你也可以加载 res/font
下的字体。
创建一个 font
文件夹可以右键 res
文件夹,选择 Android Resource Directory
-> 选择 font
Text( text = "在朋友家度过的一天,我们畅谈了许多美好的事情,由衷的庆幸大家似乎对未来有了更好的期待", fontFamily = FontFamily( Font(R.font.pingfang, FontWeight.W700) ) )
有的时候也许您需要将文本当作按钮,那么只需要添加 Modifier.clickable
即可
代码如下:
@Composable fun TextDemo() { Text( text = "确认编辑", modifier = Modifier.clickable( onClick = { // TODO }, ) ) }
取消点击波纹
但是我们会发现,clickable
有自带的波纹效果,如果我们想要取消的话,只需要添加两个参数即可:
@Composable fun TextDemo() { // 获取 context val context = LocalContext.current Text( text = "确认编辑", modifier = Modifier.clickable( onClick = { // 通知事件 Toast.makeText(context, "你点击了此文本", Toast.LENGTH_LONG).show() }, indication = null, interactionSource = MutableInteractionSource() ) ) }
效果如下:
如果我们想让一个 Text
语句中使用不同的样式,比如粗体提醒,特殊颜色
则我们需要使用到 AnnotatedString
AnnotatedString
是一个数据类,其中包含了:
一个 Text
的值
一个 SpanStyleRange
的 List
,等同于位置范围在文字值内的内嵌样式
一个 ParagraphStyleRange
的 List
,用于指定文字对齐、文字方向、行高和文字缩进样式
inline funAnnotatedString.Builder.withStyle( style: SpanStyle, block: AnnotatedString.Builder.() -> crossinline R ): R
一个简单的代码演示:
@Composable fun TextDemo() { Column( modifier = Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { Text( buildAnnotatedString { append("你现在观看的章节是 ") withStyle(style = SpanStyle(fontWeight = FontWeight.W900)) { append("Text") } } ) } }
效果如下:
在第 6 部分我们已经介绍了可以通过 AnnotatedString
来完成在一个 Text
中给不同的文字应用不同的样式
在第 5 部分我们已经介绍了可以通过 Modifier.Clickable()
来完成检测 Text
的点击
但是 Modifier.Clickable()
无法检测 Text
中的部分点击,那如果我们需要检测一个 Text
中的部分点击事件该怎么办呢?就像我们经常在 App 底下看到的用户协议等
其实很简单,Compose
也给我们准备了 ClickableText
,来看看如何使用吧!
val text = buildAnnotatedString { append("勾选即代表同意") withStyle( style = SpanStyle( color = Color(0xFF0E9FF2), fontWeight = FontWeight.Bold ) ) { append("用户协议") } } ClickableText( text = text, onClick = { offset -> Log.d(TAG, "Hi,你按到了第 $offset 位的文字") } )
但是...怎么才能检测用户协议
这四个字符的点击事件呢?
也不用怕,Compose
还在 buildAnnotatedString
和 ClickableText
中引入了相应的方法
先来看看代码吧!
val annotatedText = buildAnnotatedString { append("勾选即代表同意") pushStringAnnotation( tag = "tag", annotation = "一个用户协议啦啦啦,内容内容" ) withStyle( style = SpanStyle( color = Color(0xFF0E9FF2), fontWeight = FontWeight.Bold ) ) { append("用户协议") } pop() } ClickableText( text = annotatedText, onClick = { offset -> annotatedText.getStringAnnotations( tag = "tag", start = offset, end = offset ).firstOrNull()?.let { annotation -> Log.d(TAG, "你已经点到 ${annotation.item} 啦") } } )
在上面的代码中
多了一个 pushStringAnnotation()
方法,它会将给定的注释附加到任何附加的文本上,直到相应的 pop
被调用
getStringAnnotations()
方法是查询附加在这个 AnnotatedString
上的字符串注释。注释是附加在 AnnotatedString
上的元数据,例如,在我们的代码中 "tag"
是附加在某个范围上的字符串元数据。注释也与样式一起存储在 Range
中
小试牛刀
那么,你已经学会了如何自定义 Text
中的样式和点击事件,来尝试做出一个这样的效果?
默认情况下 Text
并不能进行复制等操作,我们需要设置 SelectionContainer
来包装 Text
@Composable fun TextDemo() { SelectionContainer { Column{ Text( text = "每天摸鱼", modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Left ) Text( text = "这好吗", modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center ) Text( text = "这非常的好", modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Right ) } } }
文字根据不同情况来确定文字的强调程度,以突出重点并体现出视觉上的层次感。
Material Design 建议采用不同的不透明度来传达这些不同的重要程度,你可以通过 LocalContentAlpha
实现此功能。
您可以通过为此 CompositionLocal
提供一个值来为层次结构指定内容 Alpha 值。(CompositionLocal
是一个用于隐式的传递参数的组件,后续会讲到)
// 将内部 Text 组件的 alpha 强调程度设置为高 // 注意: MaterialTheme 已经默认将强调程度设置为 high CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.high) { Text("这里是high强调效果") } // 将内部 Text 组件的 alpha 强调程度设置为中 CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) { Text("这里是medium强调效果") } // 将内部 Text 组件的 alpha 强调程度设置为禁用 CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.disabled) { Text("这里是禁用后的效果") }
这是运行效果:
这张图可以很好的说明这个效果
一般情况下,Text 不会水平居中,如果你在 Row
, Column
, Box
这些 Composable 里面想要实现居中的效果,你可以在 Text 外围写一个 Box
, Row
, Column
等
像这样:
Column { Text("123") Text("456") Box( modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center ) { Text("789") } }
水平靠左: Alignment.Start
水平靠右: Alignment.End
如果你的 Column
有 Modifier.fillMaxWidth()
的属性或者指定了宽度/大小,那么你可以直接在 Text 里面写 Modifier.align(Alignment.CenterHorizontally)
来让 Text 处于水平居中的位置
@Composable fun Image( painter: Painter, contentDescription: String?, modifier: Modifier = Modifier, alignment: Alignment = Alignment.Center, contentScale: ContentScale = ContentScale.Fit, alpha: Float = DefaultAlpha, colorFilter: ColorFilter? = null )
Image
可以帮我们加载一张图片。
@Composable fun ImageDemo() { Image( painter = painterResource(id = R.drawable.wallpaper), contentDescription = null ) }
我们可以使用 Modifier.size()
来设置图片大小。
@Composable fun ImageDemo() { Image( painter = painterResource(id = R.drawable.wallpaper), contentDescription = null, modifier = Modifier.size(350.dp) ) }
我们可以使用 Surface
来帮助我们设置形状,或者在 Image 组件中使用 modifier.clip() 来裁剪形状。
@Composable fun ImageDemo() { Surface( shape = CircleShape ) { Image( painter = painterResource(id = R.drawable.wallpaper), contentDescription = null, modifier = Modifier.size(350.dp) ) } }
是不是有一点小问题?似乎只有左右两边变成了圆形,而上下并没有。
这是因为 Image
中源码的 contentScale
参数默认是 ContentScale.Fit
,
也就是保持图片的宽高比,缩小到可以完整显示整张图片。
而 ContentScale.Crop
也是保持宽高比,但是尽量让宽度或者高度完整的占满。
所以我们将 contentScale
设置成 ContentScale.Crop
。
@Composable fun ImageDemo() { Surface( shape = CircleShape ) { Image( painter = painterResource(id = R.drawable.wallpaper), contentDescription = null, modifier = Modifier.size(350.dp), contentScale = ContentScale.Crop ) } }
你可以利用 Surface
中的 border
参数来设置边框。
@Composable fun ImageDemo() { Surface( shape = CircleShape, border = BorderStroke(5.dp, Color.Gray) ) { Image( painter = painterResource(id = R.drawable.wallpaper), contentDescription = null, modifier = Modifier.size(350.dp), contentScale = ContentScale.Crop ) } }
Compose 自带的 Image
只能加载资源管理器中的图片文件,如果想加载网络图片或者是其他本地路径下的文件,则需要考虑其他的库,比如 Coil
简单使用 Coil 加载网络图片:
记得打开网络权限测试
Image( painter = rememberImagePainter(data = "https://picsum.photos/300/300"), contentDescription = null )
@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, leadingIcon: @Composable (() -> Unit)? = null, trailingIcon: @Composable (() -> Unit)? = null, isError: Boolean = false, visualTransformation: VisualTransformation = VisualTransformation.None, keyboardOptions: KeyboardOptions = KeyboardOptions.Default, keyboardActions: KeyboardActions = KeyboardActions(), 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() )
下面是一个TextFiled的简单例子:
TextField( value = text, onValueChange = { text = it }, modifier = Modifier.height(20.dp) )
如果你想自定义一个 TextField
的高度,以及其他的自定义效果,你应该使用 BasicTextField
一个简单的 TextField
使用的例子是这样的:
import androidx.compose.runtime.* @Composable fun TextFieldDemo() { var text by remember{ mutableStateOf("")} TextField( value = text, onValueChange = { text = it } ) }
使用 singleLine
参数可以将 TextField
设置成只有一行
设置了 singleLine
再设置 maxLines
将无效
@Composable fun TextFieldDemo() { var text by remember{ mutableStateOf("")} TextField( value = text, onValueChange = { text = it }, singleLine = true ) }
label 标签可以运用在 TextField
中,当聚焦的时候会改变字体大小
@Composable fun TextFieldDemo() { var text by remember{ mutableStateOf("")} Column( modifier = Modifier .fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { TextField( value = text, onValueChange = { text = it }, singleLine = true, label = { Text("邮箱") } ) } }
leadingIcon
参数可以在 TextField
前面布置 lambda
表达式所接收到的东西
TextField( value = text, onValueChange = { text = it }, leadingIcon = { Icon(Icons.Filled.Search, null) }, )
虽然名字上叫做 leadingIcon
,但是 leadingIcon
接收来自一个 @Composable 函数的 lambda
表达式,
我们也可以在里面填入 Text
函数
TextField( value = text, onValueChange = { text = it }, leadingIcon = { Text("联系人") }, )
trailingIcon
参数可以在 TextField
尾部布置 lambda
表达式所接收到的东西
TextField( value = text, onValueChange = { text = it }, trailingIcon = { Text("@163.com") }, )
trailingIcon = { IconButton(onClick = { }){ Icon(Icons.Filled.Send, null) } },
@Composable fun textFieldColors( // 输入的文字颜色 textColor: Color = LocalContentColor.current.copy(LocalContentAlpha.current), // 禁用 TextField 时,已有的文字颜色 disabledTextColor: Color = textColor.copy(ContentAlpha.disabled), // 输入框的背景颜色,当设置为 Color.Transparent 时,将透明 backgroundColor: Color = MaterialTheme.colors.onSurface.copy(alpha = BackgroundOpacity), // 输入框的光标颜色 cursorColor: Color = MaterialTheme.colors.primary, // 当 TextField 的 isError 参数为 true 时,光标的颜色 errorCursorColor: Color = MaterialTheme.colors.error, // 当输入框处于焦点时,底部指示器的颜色 focusedIndicatorColor: Color = MaterialTheme.colors.primary.copy(alpha = ContentAlpha.high), // 当输入框不处于焦点时,底部指示器的颜色 unfocusedIndicatorColor: Color = MaterialTheme.colors.onSurface.copy(alpha = UnfocusedIndicatorLineOpacity), // 禁用 TextField 时,底部指示器的颜色 disabledIndicatorColor: Color = unfocusedIndicatorColor.copy(alpha = ContentAlpha.disabled), // 当 TextField 的 isError 参数为 true 时,底部指示器的颜色 errorIndicatorColor: Color = MaterialTheme.colors.error, // TextField 输入框前头的颜色 leadingIconColor: Color = MaterialTheme.colors.onSurface.copy(alpha = IconOpacity), // 禁用 TextField 时 TextField 输入框前头的颜色 disabledLeadingIconColor: Color = leadingIconColor.copy(alpha = ContentAlpha.disabled), // 当 TextField 的 isError 参数为 true 时 TextField 输入框前头的颜色 errorLeadingIconColor: Color = leadingIconColor, // TextField 输入框尾部的颜色 trailingIconColor: Color = MaterialTheme.colors.onSurface.copy(alpha = IconOpacity), // 禁用 TextField 时 TextField 输入框尾部的颜色 disabledTrailingIconColor: Color = trailingIconColor.copy(alpha = ContentAlpha.disabled), // 当 TextField 的 isError 参数为 true 时 TextField 输入框尾部的颜色 errorTrailingIconColor: Color = MaterialTheme.colors.error, // 当输入框处于焦点时,Label 的颜色 focusedLabelColor: Color = MaterialTheme.colors.primary.copy(alpha = ContentAlpha.high), // 当输入框不处于焦点时,Label 的颜色 unfocusedLabelColor: Color = MaterialTheme.colors.onSurface.copy(ContentAlpha.medium), // 禁用 TextField 时,Label 的颜色 disabledLabelColor: Color = unfocusedLabelColor.copy(ContentAlpha.disabled), // 当 TextField 的 isError 参数为 true 时,Label 的颜色 errorLabelColor: Color = MaterialTheme.colors.error, // Placeholder 的颜色 placeholderColor: Color = MaterialTheme.colors.onSurface.copy(ContentAlpha.medium), // 禁用 TextField 时,placeholder 的颜色 disabledPlaceholderColor: Color = placeholderColor.copy(ContentAlpha.disabled) )
调用方法
TextField( value = text, onValueChange = { text = it }, leadingIcon = { Icon(Icons.Filled.Search, null) }, colors = TextFieldDefaults.textFieldColors( textColor = Color(0xFF0079D3), backgroundColor = Color.Transparent ) )
在你使用 IDE 智能补全的时候可能遇到这种情况
解决方法如下,手动打完函数名
visualTransformation
可以帮助我们应用输入框的显示模式
var text by remember{mutableStateOf("")} var passwordHidden by remember{ mutableStateOf(false)} TextField( value = text, onValueChange = { text = it }, trailingIcon = { IconButton( onClick = { passwordHidden = !passwordHidden } ){ Icon(painterResource(id = R.drawable.visibility), null) } }, label = { Text("密码") }, visualTransformation = if(passwordHidden) PasswordVisualTransformation() else VisualTransformation.None )
@Composable fun BasicTextField( value: String, onValueChange: (String) -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, readOnly: Boolean = false, textStyle: TextStyle = TextStyle.Default, keyboardOptions: KeyboardOptions = KeyboardOptions.Default, keyboardActions: KeyboardActions = KeyboardActions.Default, singleLine: Boolean = false, maxLines: Int = Int.MAX_VALUE, visualTransformation: VisualTransformation = VisualTransformation.None, onTextLayout: (TextLayoutResult) -> Unit = {}, // 当输入框内文本触发更新时候的回调,包括了当前文本的各种信息 interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, cursorBrush: Brush = SolidColor(Color.Black), // 输入框光标的颜色 decorationBox: @Composable (innerTextField: @Composable () -> Unit) -> Unit = @Composable { innerTextField -> innerTextField() } // 是一个允许在 TextField 周围添加修饰的 @Composable lambda // 我们需要在布局中调用 innerTextField() 才能完成 TextField 的构建 )
使用 BasicTextField
可以让你拥有更高的自定义效果
一个简单的使用例子如下:
var text by remember { mutableStateOf("") } Box( modifier = Modifier .fillMaxSize() .background(Color(0xFFD3D3D3)), contentAlignment = Alignment.Center ) { BasicTextField( value = text, onValueChange = { text = it }, modifier = Modifier .background(Color.White, CircleShape) .height(35.dp) .fillMaxWidth(), decorationBox = { innerTextField -> Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(horizontal = 10.dp) ) { IconButton( onClick = { } ) { Icon(painterResource(id = R.drawable.mood), null) } Box( modifier = Modifier.weight(1f), contentAlignment = Alignment.CenterStart ) { innerTextField() } IconButton( onClick = { }, ) { Icon(Icons.Filled.Send, null) } } } ) }
在刚才的例子中,我们在 decorationBox 里面写了很多布局组件,最后通过调用一次 innerTextFiled() 来完成输入框的构建。
@OptIn(ExperimentalMaterialApi::class) @Composable fun Button( onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, elevation: ButtonElevation? = ButtonDefaults.elevation(), shape: Shape = MaterialTheme.shapes.small, border: BorderStroke? = null, colors: ButtonColors = ButtonDefaults.buttonColors(), contentPadding: PaddingValues = ButtonDefaults.ContentPadding, content: @Composable RowScope.() -> Unit )
Compose 的 Button
是基于 Material Design 理念设计的
2.1 基本使用
以下是简单创建一个默认的 Button
代码:
import androidx.compose.material.Button import androidx.compose.material.Text @Composable fun ButtonDemo() { Button( onClick = { /*TODO*/ } ) { Text("确认") } }
效果如图所示:
也许您想添加图标在文字的旁边,也只需:
@Composable fun ButtonDemo() { Button(onClick = { /*TODO*/ }) { Icon( // Material 库中的图标,有 Filled, Outlined, Rounded, Sharp, Two Tone 等 Icons.Filled.Favorite, contentDescription = null, modifier = Modifier.size(ButtonDefaults.IconSize) ) // 添加间隔 Spacer(Modifier.size(ButtonDefaults.IconSpacing)) Text("喜欢") } }
2.2 不同点击状态下的按钮状态
创建 Data class
来记录不同状态下按钮的样式
data class ButtonState(var text: String, var textColor: Color, var buttonColor: Color)
使用 MutableInteractionSource() 获取状态,根据不同状态创建样式
// 获取按钮的状态 val interactionState = remember { MutableInteractionSource() } // 使用 Kotlin 的解构方法 val (text, textColor, buttonColor) = when { interactionState.collectIsPressedAsState().value -> ButtonState("Just Pressed", Color.Red, Color.Black) else -> ButtonState( "Just Button", Color.White, Color.Red) }
Button
的实现
Button( onClick = { /*TODO*/ }, interactionSource = interactionState, elevation = null, shape = RoundedCornerShape(50), colors = ButtonDefaults.buttonColors( backgroundColor = buttonColor, ), modifier = Modifier.width(IntrinsicSize.Min).height(IntrinsicSize.Min) ) { Text( text = text, color = textColor ) }
@Composable fun AlertDialog( onDismissRequest: () -> Unit, confirmButton: () -> Unit, modifier: Modifier = Modifier, dismissButton: () -> Unit = null, title: () -> Unit = null, text: () -> Unit = null, shape: Shape = MaterialTheme.shapes.medium, backgroundColor: Color = MaterialTheme.colors.surface, contentColor: Color = contentColorFor(backgroundColor), properties: DialogProperties = DialogProperties() ): @Composable Unit
val openDialog = remember { mutableStateOf(true) } if (openDialog.value) { AlertDialog( onDismissRequest = { // 当用户点击对话框以外的地方或者按下系统返回键将会执行的代码 openDialog.value = false }, title = { Text( text = "开启位置服务", fontWeight = FontWeight.W700, style = MaterialTheme.typography.h6 ) }, text = { Text( text = "这将意味着,我们会给您提供精准的位置服务,并且您将接受关于您订阅的位置信息", fontSize = 16.sp ) }, confirmButton = { TextButton( onClick = { openDialog.value = false }, ) { Text( "确认", fontWeight = FontWeight.W700, style = MaterialTheme.typography.button ) } }, dismissButton = { TextButton( onClick = { openDialog.value = false } ) { Text( "取消", fontWeight = FontWeight.W700, style = MaterialTheme.typography.button ) } } ) }
如果一切顺利,运行程序,您将会看到:
AlertDialog
将根据可用空间来定位其按钮。默认情况下,它将尝试将它们水平地放在彼此的旁边,如果没有足够的空间,则退回到水平放置。还有另一个版本的 Composable,它有一个按钮槽,可以提供自定义的按钮布局
@Composable fun AlertDialog( onDismissRequest: () -> Unit, buttons: () -> Unit, modifier: Modifier = Modifier, title: () -> Unit = null, text: () -> Unit = null, shape: Shape = MaterialTheme.shapes.medium, backgroundColor: Color = MaterialTheme.colors.surface, contentColor: Color = contentColorFor(backgroundColor), properties: DialogProperties = DialogProperties() ): @Composable Unit
简单的一个实现代码:
val openDialog = remember { mutableStateOf(true) } if (openDialog.value) { AlertDialog( onDismissRequest = { openDialog.value = false }, title = { Text( text = "开启位置服务", fontWeight = FontWeight.W700, style = MaterialTheme.typography.h6 ) }, text = { Text( text = "这将意味着,我们会给您提供精准的位置服务,并且您将接受关于您订阅的位置信息", fontSize = 16.sp ) }, buttons = { Row( modifier = Modifier.padding(all = 8.dp), horizontalArrangement = Arrangement.Center ) { Button( modifier = Modifier.fillMaxWidth(), onClick = { openDialog.value = false } ) { Text("必须接受!") } } } ) }
AlertDialog
在一些情况下有可能还是无法满足我们的业务要求,这时候我们就可以使用更底层的一个 @Composable 函数 —— Dialog
var flag by remember{ mutableStateOf(false) } Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { Button( onClick = { flag = true } ) { Text("弹窗") } } if(flag) { Dialog( onDismissRequest = { flag = false } ) { Box( modifier = Modifier .size(300.dp) .background(Color.White), contentAlignment = Alignment.Center ) { Column { LinearProgressIndicator() Text("加载中 ing...") } } } }