對於用戶界面而言,文本是最基礎而又核心的內容,在傳統的 Android Native 開發中,須要用一個TextView來顯示一個文本。在Jetpack Compose 中,提供了Text可組合函數(即組件,後面的文章都會稱其爲「組件」),可更輕鬆的顯示文本。在本文中,將帶你們一塊兒探索Text組件的各類用法。app
在Jetpack Compose 中,組件是一個特殊的Kotlin 函數,所以Text其實也是一個函數,而它提供了不少參數來配置文本的顯示外觀。這些參數就是組件的屬性。看一下Text組件有哪些屬性:函數
@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 ) { ... }
Jetpack Compose 中,不少地方都用到了Kotlin 的特性,好比這裏,就用到Kotlin的默認參數,Text 組件除了第一個參數text
,其餘都有默認值,也就是使用的時候能夠不傳,可是若是傳多個參數時,必定要加參數名。好比,設置大小:佈局
@Composable fun MyText(){ Text("Jetpack Compose,by 依然範特稀西", fontSize = 20.sp ) }
第一個參數能夠加參數名,也能夠不加,但我我的仍是推薦加上,由於他是一個組件,參數是它的屬性,這樣代碼比較直觀。像下面這樣就比較好一點:字體
@Composable fun MyText(){ Text( text = "Jetpack Compose,by 依然範特稀西", fontSize = 20.sp ) }
知道了,每一個屬性的意思,咱們接下來一塊兒看看,配置各屬性後的效果展現。動畫
對於用戶界面而言,文本是最基礎而又核心的內容,在傳統的 Android Native 開發中,須要用一個TextView來顯示一個文本。在Jetpack Compose 中,提供了Text可組合函數(即組件,後面的文章都會稱其爲「組件」),可更輕鬆的顯示文本。在本文中,將帶你們一塊兒探索Text組件的各類用法。ui
在Jetpack Compose 中,組件是一個特殊的Kotlin 函數,所以Text其實也是一個函數,而它提供了不少參數來配置文本的顯示外觀。這些參數就是組件的屬性。看一下Text組件有哪些屬性:spa
@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 ) { ... }
Jetpack Compose 中,不少地方都用到了Kotlin 的特性,好比這裏,就用到Kotlin的默認參數,Text 組件除了第一個參數text
,其餘都有默認值,也就是使用的時候能夠不傳,可是若是傳多個參數時,必定要加參數名。好比,設置大小:code
@Composable fun MyText(){ Text("Jetpack Compose,by 依然範特稀西", fontSize = 20.sp ) }
第一個參數能夠加參數名,也能夠不加,但我我的仍是推薦加上,由於他是一個組件,參數是它的屬性,這樣代碼比較直觀。像下面這樣就比較好一點:orm
@Composable fun MyText(){ Text( text = "Jetpack Compose,by 依然範特稀西", fontSize = 20.sp ) }
知道了,每一個屬性的意思,咱們接下來一塊兒看看,配置各屬性後的效果展現。xml
顯示文字的最簡單的方法是使用以 String 做爲參數的 Text 組件:
@Composable fun MyText(){ Text("Jetpack Compose,by 依然範特稀西") }
也能夠顯示字符串資源,這也是推薦的方式,而不是直接將字符串寫死在代碼中,這樣有利於替換或者國際化。
<!-- xml資源文件--> <resources> <string name="my_text">Jetpack Compose,by 依然範特稀西</string> </resources> @Composable fun MyText(){ Text(stringResource(R.string.my_text)) }
@Composable fun MyText() { Text( text = stringResource(R.string.my_text), color = Color.Blue ) }
@Composable fun MyText() { Text( text = stringResource(R.string.my_text), color = Color.Blue, fontSize = 30.sp, ) }
fontStyle
有2個取值,FontStyle.Italic
和FontStyle.Normal
@Composable fun MyText() { Column{ Text( text = stringResource(R.string.my_text), fontStyle = FontStyle.Normal, ) Text( text = stringResource(R.string.my_text), fontStyle = FontStyle.Italic, ) } }
fontWeight
能夠取 1- 1000之間的值,使用的時候,構造一個FontWeight
便可:
FontWeight(50)
FontWeight 默認爲咱們定義幾個默認值,100-900的整百值,並根據他們的顯示效果取名爲Bold
,Light
,Thin
等等。
companion object { /** [Thin] */ @Stable val W100 = FontWeight(100) /** [ExtraLight] */ @Stable val W200 = FontWeight(200) /** [Light] */ @Stable val W300 = FontWeight(300) /** [Normal] / regular / plain */ @Stable val W400 = FontWeight(400) /** [Medium] */ @Stable val W500 = FontWeight(500) /** [SemiBold] */ @Stable val W600 = FontWeight(600) /** [Bold] */ @Stable val W700 = FontWeight(700) /** [ExtraBold] */ @Stable val W800 = FontWeight(800) /** [Black] */ @Stable val W900 = FontWeight(900) /** Alias for [W100] */ @Stable val Thin = W100 /** Alias for [W200] */ @Stable val ExtraLight = W200 /** Alias for [W300] */ @Stable val Light = W300 /** The default font weight - alias for [W400] */ @Stable val Normal = W400 /** Alias for [W500] */ @Stable val Medium = W500 /** Alias for [W600] */ @Stable val SemiBold = W600 /** * A commonly used font weight that is heavier than normal - alias for [W700] */ @Stable val Bold = W700 /** Alias for [W800] */ @Stable val ExtraBold = W800 /** Alias for [W900] */ @Stable val Black = W900 /** A list of all the font weights. */ internal val values: List<FontWeight> = listOf( W100, W200, W300, W400, W500, W600, W700, W800, W900 )
看一下他們的顯示效果:
@Composable fun MyText() { Column { Text( text = stringResource(R.string.my_text), fontWeight = FontWeight.Thin, ) Text( text = stringResource(R.string.my_text), fontWeight = FontWeight.ExtraLight ) Text( text = stringResource(R.string.my_text), fontWeight = FontWeight.Light ) Text( text = stringResource(R.string.my_text), fontWeight = FontWeight.Normal ) Text( text = stringResource(R.string.my_text), fontWeight = FontWeight.Medium ) Text( text = stringResource(R.string.my_text), fontWeight = FontWeight.SemiBold ) Text( text = stringResource(R.string.my_text), fontWeight = FontWeight.Bold ) Text( text = stringResource(R.string.my_text), fontWeight = FontWeight.ExtraBold ) Text( text = stringResource(R.string.my_text), fontWeight = FontWeight.Black ) } }
fontFamily
能夠更改字體,FontFamily爲咱們默認內置了5種字體,Default
、SansSerif
、Serif
、Monospace
、Cursive
。
@Composable fun MyText() { Column { Text( text = stringResource(R.string.my_text), fontFamily = FontFamily.Default, ) Text( text = stringResource(R.string.my_text), fontFamily = FontFamily.SansSerif ) Text( text = stringResource(R.string.my_text), fontFamily = FontFamily.Serif ) Text( text = stringResource(R.string.my_text), fontFamily = FontFamily.Monospace ) Text( text = stringResource(R.string.my_text), fontFamily = FontFamily.Cursive ) } }
letterSpacing
更改文字間距,更確切的說是更改字符間距,由於若是是英文的話,不會按單詞來設置間距,而是按字母。
@Composable fun MyText() { Text( text = stringResource(R.string.my_text), letterSpacing = 10.sp, ) }
textDecoration
能夠給文字裝飾下劃線和中劃線。默認提供了三個值:
None
: 無裝飾效果LineThrough
: 添加中劃線Underline
: 添加下劃線@Composable fun MyText() { Column { Text( text = stringResource(R.string.my_text), textDecoration = TextDecoration.None, ) Text( text = stringResource(R.string.my_text), textDecoration = TextDecoration.LineThrough, ) Text( text = stringResource(R.string.my_text), textDecoration = TextDecoration.Underline, ) } }
除此以外,TextDecoration
還提供了一個combine
函數,能夠將下劃線和中劃線組合:
@Composable fun MyText() { val combineDecoration = listOf(TextDecoration.Underline, TextDecoration.LineThrough) Text( text = stringResource(R.string.my_text), textDecoration = TextDecoration.combine(combineDecoration) ) }
textAlign
能夠設置Text組件內容的對齊方式,有TextAlign.Start
、TextAlign. End
、TextAlign. Center
、TextAlign. Justify
等值。默認狀況下,Text 會根據其內容值選擇天然的文字對齊方式:
若是您想手動設置 Text 組件的文字對齊方式,最好分別使用TextAlign.Start
和TextAlign.End
(而不要使用TextAlign.Left
和TextAlign.Right
),這樣系統就能夠根據具體語言的首選文字方向,將您的設置解析爲向 Text 的右邊緣對齊。例如,TextAlign.End
對於法語文字將向右側對齊,而對於阿拉伯語文字則將向左側對齊,但不管對於哪一種文字,TextAlign.Right
都將向右側對齊。
@Composable fun MyText() { Column { Text( text = stringResource(R.string.my_text), modifier = Modifier .size(300.dp, 50.dp) .background(Color.Gray), textAlign = TextAlign.Start ) Text( text = stringResource(R.string.my_text), modifier = Modifier .size(300.dp, 50.dp) .background(Color.Gray), textAlign = TextAlign.End ) Text( text = stringResource(R.string.my_text), modifier = Modifier .size(300.dp, 50.dp) .background(Color.Gray), textAlign = TextAlign.Center ) Text( text = stringResource(R.string.my_text), modifier = Modifier .size(300.dp, 50.dp) .background(Color.Gray), textAlign = TextAlign.Justify ) } }
注意:要對齊方式生效,須要給Text設置大小,由於Text組件默認的大小是包裹內容的,上面的代碼咱們用
modifier
屬性設置了Text組件的大小。
lineHeight
設置行高,值爲一個具體數值,單位爲sp
@Composable fun MyText() { Column { Text( text = "未設置lineHeight".repeat(10), ) Text( text = "已經設置lineHeight".repeat(10), lineHeight = 30.sp ) } }
overflow
設置當文本超出控件時的顯示樣式,有兩個取值:
TextOverflow.Clip
: 超出部分直接截斷TextOverflow.Ellipsis
: 使用省略號表示文本已溢出overflow
通常配合maxLines
使用
@Composable fun MyText() { Column { Text( text = stringResource(R.string.my_text).repeat(10), overflow = TextOverflow.Clip, maxLines = 2 ) Spacer(modifier = Modifier.height(20.dp)) Text( text = stringResource(R.string.my_text).repeat(10), overflow = TextOverflow.Ellipsis, maxLines = 2 ) } }
maxLines
配置最多顯示幾行,該屬性通常須要配置overflow
,代表超出部分該如何顯示,默認直接截斷(Clip效果)。
@Composable fun MyText() { Column { Text( text = stringResource(R.string.my_text).repeat(10), ) Spacer(modifier = Modifier.height(20.dp)) Text( text = stringResource(R.string.my_text).repeat(10), maxLines = 2, ) } }
默認爲true
,即會自動換行,若是設置爲false
,將不會自動換行。通常使用場景爲:文本單行顯示,超出默認截斷或顯示省略號
,即配合overflow
使用:
@Composable fun MyText() { Text( text = stringResource(R.string.my_text).repeat(10), softWrap = false, overflow = TextOverflow.Ellipsis ) }
計算新的Text佈局時回調函數,回調中能夠獲取一些結果,好比控件的size等。
@Composable fun MyText() { Text( text = stringResource(R.string.my_text), onTextLayout = { Log.e("xige","text width: ${it.size.width}, text height: ${it.size.height}") } ) }
運行結果:
顏色、字號、行高等那些屬性效果,均可以用style
來統一配置,除此以外,還有一些屬性,如:shadow
能夠設置倒影效果,全部可配置屬性以下:
@Composable fun MyText() { Text( text = stringResource(R.string.my_text), style = TextStyle( color = Color.Blue, fontSize = 20.sp, lineHeight = 20.sp, fontWeight = FontWeight.Bold, fontFamily = FontFamily.Monospace, fontStyle = FontStyle.Normal, shadow = Shadow( color = Color.Red, offset = Offset(10.0f,10.0f), blurRadius = 10.0f ) ) ) }
最後來講說modifier,這個屬性很重要,也不是Text組件所獨有,基本全部組件都有這個屬性,它能夠修改組件外觀好比:pading、寬高、背景、形狀等等。但毫不僅於此,還要不少強大的功能,能夠定義動畫,自定義點擊事件等等。因爲篇幅有限,後面會單獨寫一篇Modifier的文章介紹。
@Composable fun MyText() { Text( text = stringResource(R.string.my_text), modifier = Modifier .border( width = 3.dp, color = Color.Red, shape = RoundedCornerShape( topStart = 30.dp, topEnd = 30.dp, bottomStart = 20.dp, bottomEnd = 30.dp ) ) .size(400.dp, 50.dp) .padding(10.dp) ) }
默認狀況下,Text組件內容不可選擇
,這意味着,在默認狀況下用戶沒法從你的應用中選擇和複製
文字。要啓用文字選擇,須要使用 SelectionContainer
容器包裝Text元素。
從字面意思看:可選擇的容器,確實,只要用SelectionContainer
包裝Text,則可選擇Text組件顯示的文本。
@Composable fun MyText() { SelectionContainer { Text(stringResource(R.string.my_text)) } }
##### DisableSelection組件
JetpackCompose 其實支持更精細化的選擇,假設你想在一段可選擇的文本中,嵌入一個不可被選擇的文本。要實現這樣一個功能很是簡單,使用DisableSelection
組件便可。
被 DisableSelection
包裹的Text組件,內容不可被選擇:
@Composable fun MyText() { SelectionContainer { Column { Text("我是可被選中文本1") Text("我是可被選中文本2") Text("我是可被選中文本3") DisableSelection { Text("我是不可被選中文本1") Text("我是不可被選中文本2") } Text("我是可被選中文本4") Text("我是可被選中文本4") } } }
Text 組件自己是沒有點擊事件的,若是要讓Text可點擊,能夠給它添加clickable
修飾符,也就是咱們前面說的Modifier,以下,咱們添加一個可點擊Text,點擊一次增長1
:
@Composable fun MyText() { val txt = remember { mutableStateOf(0)} Column( modifier = Modifier .fillMaxSize() .background(Color(0xFFE5E4E2)) .padding(16.dp), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Text( text = "${txt.value}", fontFamily = FontFamily.Serif, fontSize = 75.sp, color = Color(0xFFE63E62), modifier = Modifier .clip(RoundedCornerShape(12.dp)) .background(Color(0xFFC9C0BB)) .clickable( enabled = true, role = Role.Button ){ txt.value += 1 } .padding(25.dp) ) } }
clickable
能夠給Text添加點擊事件,可是它卻不能監聽點擊的是Text的那個位置,好比顯示的是Jetpack Compose,by 依然範特稀西
,我想肯定點擊的是哪一個字符,該咋整呢?Compose 爲咱們提供了支持,使用ClickableText
便可:
@Composable fun MyText() { ClickableText( text = AnnotatedString(stringResource(R.string.my_text)) ) { index -> Log.d("ClickableText", "第 $index 個字符被點擊") } }
注意ClickableText
接受的是一個 AnnotatedString
類型,最後一個參數就是onClick
,這裏運用了kotlin的lamuda表達式特性,最後一個lamuda表達式能夠提到括號外,跟下面是等價的。
@Composable fun MyText() { ClickableText( text = AnnotatedString(stringResource(R.string.my_text)), onClick = { index -> Log.d("ClickableText", "第 $index 個字符被點擊") } ) }
Text 支持爲其中的字符、字符串單獨設置不一樣的樣式,由於Text組件的text屬性是AnnotatedString
類型,AnnotatedString
是一個數據類:
class AnnotatedString internal constructor( val text: String, // 字符串 val spanStyles: List<Range<SpanStyle>> = emptyList(), // 設置字符樣式的List val paragraphStyles: List<Range<ParagraphStyle>> = emptyList(), //設置段落樣式的List internal val annotations: List<Range<out Any>> = emptyList() // 註解list )
咱們能夠經過提供的buildAnnotatedString
來構建AnnotatedString 類,其中,能夠經過append
函數拼接字符串,能夠經過withStyle
拼接字符串並設置樣式:
@Composable fun MyText() { Text( buildAnnotatedString { withStyle( style = SpanStyle( color = Color.Blue, fontWeight = FontWeight.Bold ) ) { append("Jetpack ") } append("Compose ") withStyle( style = SpanStyle( color = Color.Red, fontWeight = FontWeight.Bold, fontSize = 30.sp ) ) { append("by ") } append("依然範特稀西") } ) }
這裏咱們使用了SpanStyle
來設置單個樣式,還有一個ParagraphStyle
,按字面理解,就是設置段落樣式,也就是包裹在ParagraphStyle裏面的段落都會應用它設置的樣式,看一下示例:
@Composable fun MyText() { Text( buildAnnotatedString { withStyle( // 設置段落樣式 style = ParagraphStyle( lineHeight = 60.sp, textAlign = TextAlign.Center ) ) { withStyle( style = SpanStyle( color = Color.Blue, fontWeight = FontWeight.Bold ) ) { append("Jetpack Compose\n") } withStyle( style = SpanStyle( color = Color.Red, fontWeight = FontWeight.Bold, fontSize = 30.sp ) ) { append("by\n") } withStyle( style = SpanStyle( color = Color.Green, fontWeight = FontWeight.Bold, ) ) { append("依然範特稀西\n") } withStyle( style = SpanStyle( fontWeight = FontWeight.Bold, fontSize = 30.sp, color = Color.Red ) ) { append("@公衆號:技術最TOP ") } } }, modifier = Modifier.width(400.dp) ) }
上面,設置的lineHeight
和textAlin
樣式應用到了所包裹的全部段落上。
咱們的APP中,登陸/註冊頁面都會有隱私政策協議
,須要用戶贊成後才能繼續,像下面這樣:
點擊藍色字便可跳轉到隱私政策/用戶協議界面,通常是一個H5頁面。咱們來用Jetpack Compose實現這麼一個功能。
思路: ClickText
+ 樣式嵌套
+ 點擊註解
可實現
前兩個已經介紹過了,如今簡單說說點擊註解
:在使用buildAnnotatedString
時,可使用pushStringAnnotation
攜帶一個tag數據, 在點擊對應tag時, onClick 中,可使用getStringAnnotations
獲取攜帶的數據。
@Composable fun MyText() { val annotatedText = buildAnnotatedString { append("登陸即代表贊成") pushStringAnnotation( tag = "tag1", annotation = "隱私條款1:https://www.xxx1.com" ) withStyle( style = SpanStyle( color = Color.Blue, fontWeight = FontWeight.Bold, textDecoration = TextDecoration.Underline ) ) { append("中國移動認證服務條款") } pop() append("以及") pushStringAnnotation( tag = "tag2", annotation = "隱私條款2:https://www.xxx2.com" ) withStyle( style = SpanStyle( color = Color.Blue, fontWeight = FontWeight.Bold, textDecoration = TextDecoration.Underline ) ) { append("用戶協議") } pop() append("和") pushStringAnnotation( tag = "tag1", annotation = "隱私條款3:https://www.xxx3.com" ) withStyle( style = SpanStyle( color = Color.Blue, fontWeight = FontWeight.Bold, textDecoration = TextDecoration.Underline ) ) { append("隱私政策") } pop() } val tags = listOf("tag1", "tag2", "tag3") ClickableText( text = annotatedText, onClick = { offset -> tags.forEach { tag -> annotatedText.getStringAnnotations( tag = tag, start = offset, end = offset ) .firstOrNull()?.let { annotation -> Log.d("xige", annotation.item) } } } ) }
點擊藍色字,打印以下:
在真實場景中,只須要將打印的地方,換跳轉Webview展現便可。
以上就是Jetpack Compose中,Text組件使用的介紹,以及文字顯示的各類使用探索。歡迎你們留言交流。
我是西哥,歡迎你們關注個人公衆號:「技術最TOP」,乾貨內容第一時間送閱!