原文: Jetpack Compose學習(2)——文字(Text)的使用 | Stars-One的雜貨小窩
對於開發來說,文字最為基礎的元件,我們先從這兩個使用開始吧
本篇涉及到Kotlin和DSL特性的使用 若不瞭解的話可能會造成程式碼閱讀困難,閱讀前確保你有上述基礎知識!!!
本系列以往文章請檢視此分類連結jetpackcompose學習
基礎使用
@Preview(showBackground = true)
@Composable
fun textDemo() {
ComposeDemoTheme {
Column() {
//基礎使用
Text(text = "Hello world")
//文字顏色
Text(text = "Hello world", color = Color.Blue)
//文字大小,sp關鍵字需要匯入
Text("Hello World", fontSize = 30.sp)
//斜體
Text("Hello World", fontStyle = FontStyle.Italic)
//字型加粗
Text("Hello World", fontWeight = FontWeight.Bold)
//文字溢位(顯示省略號) repeat是重複的意思,文字內容是20個Hello world組成的字串
Text(text = "Hello world".repeat(20),overflow = TextOverflow.Ellipsis,maxLines = 2)
}
}
}
上述程式碼的效果如下圖所示:
屬性 | 說明 |
---|---|
text | 文字 |
color | 文字顏色 |
fontSize | 字型大小 |
fontStyle | 字型樣式, 可設定為斜體Italic |
fontWeight | 字型權重,可設定字型加粗 |
overflow | 文字溢位效果,與maxLines結合使用可實現文字溢位顯示省略號效果 |
maxLines | 最大行數 ,與overflow結合使用實現文字溢位顯示省略號效果 |
PS:這裡提下,還有個重要的屬性
modifier
,這個準備在和佈局使用一起講解,其作用很強大,可以設定控制元件寬高,背景,點選效果,間距,滾動等效果,所有的元件都是存在有這個屬性,方便我們對元件進行調整
上述列出的屬性並不是全部,還有些不是太常用的就沒列出來了
補充: 一般我們是將常用的文字放在
string.xml
檔案中,如果想要獲取這裡的數值,compose也是提供有相應的方法,當然,除了文字之外,顏色等資源也有對應的方法文字 ->
stringResource(R.string.app_name)
顏色 ->
colorResource(R.color.black)
尺寸 ->
dimensionResource(R.dimen.padding_small)
圖片 ->
painterResource(R.drawable.ic_logo)
單行文字多樣式
我們可能遇到這樣的情況,在一行文字中,其中某個地址可以點選,或者某個詞語需要加粗,按照以往的操作,我們就得用多個TextView來實現或藉助他人封裝的View來實現
但在Compose中,我們可以很方便的實現上述這樣的效果,text
屬性除了接收字串,還可以接收一個引數AnnotatedString
,如下圖所示
提示:如果你快捷鍵是預設的話,在方法括號裡按下
ctrl+p
可以看到引數提示 :good:
官方文件的解釋:
The basic data structure of text with multiple styles.
翻譯過來就是說AnnotatedString
是一種具有多種樣式的文字的基本資料結構
文件上也是說明了,推薦可以使用構建器來生成物件,其實也就是一個方法buildAnnotatedString()
此方法裡面我們可以使用Kotlin的語言特性DSL,更方便的建立一個AnnotatedString
來段簡單的程式碼:
@Composable
fun ParagraphStyle() {
Text(
buildAnnotatedString {
withStyle(style = ParagraphStyle(lineHeight = 30.sp)) {
//設定Hello為藍色字型
withStyle(style = SpanStyle(color = Color.Blue)) {
append("Hello")
}
}
}
)
}
buildAnnotatedString方法裡存在有withStyle
和append
方法,這兩個方法其實是AnnotatedString.Builder
類裡的方法
這裡是採用了lambda寫法,buildAnnotatedString花括號裡的物件即為AnnotatedString.Builder
withStyle可以接收ParagraphStyle
或SpanStyle
從字面上很容易理解,ParagraphStyle
是段落樣式,SpanStyle
是單行樣式
從構造方法來看,SpanStyle
其實和Text的構造方法差不多,而且比Text類中的屬性都要豐富,如設定背景色,陰影等(而Text類中這些功能都被封裝在Modified類裡)
前面列出的屬性表格它都有,但除了text屬性(當然,也能理解,這只是個Style,要text屬性做什麼 ) ?
而ParagraphStyle
稍微比較少一點,主要以排版的屬性為主,如對齊,行高,文字方向等,從下圖可以看得出來
append
方法也容易理解,就是你想要把樣式賦值給哪個文字
然後我們就可以無限套娃,組合出我們想要的樣式 ?
Text(buildAnnotatedString {
withStyle(ParagraphStyle()) {
append("stars-one")
withStyle(SpanStyle(color = Color.Black)) {
append("的網站:")
}
withStyle(SpanStyle(color = Color.Red)) {
append("stars-one.site")
}
}
//新起段落
withStyle(ParagraphStyle()) {
append("newLine")
}
})
效果如下圖:
PS:換行的話也可以輸入
\n
轉義符號
文字長按可選擇
預設情況下,Text是無法選擇的,compose中提供了一個容器SelectionContainer
,方便我們實現Text的選擇效果
@Composable
fun SelectableText() {
SelectionContainer {
Text("This text is selectable")
}
}
可點選文字
設定文字的點選事件我們可以使用Modifier提供的方法,點選會有有水波漣漪的效果
Text(
text = "Hello world",
modifier = Modifier.clickable {
//點選事件
}
)
如果你有存在是判斷點選的位置需求,官方則是推薦使用ClickableText
這個控制元件,此控制元件只接受AnnotatedString
文字,不接受常規字串文字引數
ClickableText(
text = AnnotatedString("Click Me"),
onClick = { offset ->
//offset是你點選的時候是點了哪個文字
//如你點了C,那麼offset為0
}
)
點選文字跳轉連結
我們常見的文字,會在一段文字中間有個連結文字,點選會跳轉瀏覽器從而開啟到具體的頁面H5
輸入使用上面的效果也是能完成效果,但是每次還得算下下標的範圍才符合條件,這樣過於繁瑣
對此情況,官方也是有對應的解決方法,在AnnotatedString
構造的時候,使用pushStringAnnotation()
和pop()
方法即可達到效果,如下面給出的程式碼
val annotatedText = buildAnnotatedString {
append("Click ")
//設定存放的資料和標籤
pushStringAnnotation(tag = "URL",annotation = "https://developer.android.com")
withStyle(style = SpanStyle(color = Color.Blue,fontWeight = FontWeight.Bold)) {
append("here")
}
//代表結束
pop()
}
在構造的時候,使用pushStringAnnotation()
存下相應的資料,之後在點選事件中通過AnnotatedString
的getStringAnnotations()
方法重新獲取內容,之後進行相應的邏輯操作(如跳轉地址)
可以看到,pushStringAnnotation()
方法中存在有兩個引數,tag
代表標籤,資料可以隨意定義,但要與之後呼叫getStringAnnotations()
傳參需要對應上,annotation
則是存放的資料(只支援String)
記得在後面需要呼叫pop()
方法,這兩個方法是需要結合使用的,上述程式碼就是把here這個詞設定了一個額外資料內容
我們還是使用ClickableText
這個類,在點選事件中獲取引數即可
@Composable
fun AnnotatedClickableText() {
val annotatedText = buildAnnotatedString {
append("Click ")
pushStringAnnotation(tag = "URL",annotation = "https://developer.android.com")
withStyle(style = SpanStyle(color = Color.Blue,
fontWeight = FontWeight.Bold)) {
append("here")
}
pop()
}
ClickableText(
text = annotatedText,
onClick = { offset ->
val annotationList = annotatedText.getStringAnnotations(tag = "URL", start = offset,nd = offset)
//firstOrNull是找List中的第一個物件,找不到則則返回null
annotationList.firstOrNull()?.let { annotation ->
val url = annotation.item
//後面即邏輯操作...
}
}
)
}
需要注意的是,
getStringAnnotations()
傳了之前設定的tags引數的內容及開始和結束的下標,返回的是一個List物件
這裡返回List也不難理解,getStringAnnotations()
方法作用就是搜尋文字的指定下標範圍內,存在有tags的內容資料,指定下標範圍內,若tags相同,應該也是會被收集到
但是我覺得應該不會用這種情況的發生,但是為了確保使用,tags
引數的數值我們最好設定一個唯一的數值