iT邦幫忙

2022 iThome 鐵人賽

DAY 14
2

前言


昨天介紹了 Brush 如何套用在字體,以及重複上色的模式TileMode,今天帶來用圖片作為字體色,以及指定範圍內字體套用筆刷風格的方法。

用圖片顏色渲染字體


除了用顏色list來做出字體顏色之外,圖片一樣可以成為字體顏色的來源。

原圖 渲染字體
https://ithelp.ithome.com.tw/upload/images/20220920/20136048Ksygh8XfAw.jpg https://ithelp.ithome.com.tw/upload/images/20220920/20136048gJMJD4oZzf.png
@OptIn(ExperimentalTextApi::class)
@Preview(showBackground = true) 
@Composable
fun ImageColor() {
    val res = LocalContext.current.resources
    val brush = remember {
        ShaderBrush(
            BitmapShader(
                ImageBitmap.imageResource(res,R.drawable.android_img).asAndroidBitmap(),
                android.graphics.Shader.TileMode.REPEAT, //x軸如何重複筆刷
                android.graphics.Shader.TileMode.REPEAT  //y軸如何重複筆刷
            )
        )
    }

    Text(
        text = myText,//帶入文字
        style = TextStyle(brush = brush)
    )
}

要做出以底圖取色的樣式,要用 ShaderBrush 帶入參數 [BitmapShader](https://developer.android.com/reference/android/graphics/BitmapShader)

這裡特別注意要把 brushremember 儲存起來,因為建立 shader 是很耗資源的,才不會在重組(recompositions)時又要重新配置資源給 brush

這個表現手法我在網頁版中比較常看到,例如為了凸現 Logo 或是做出像是報紙襯底背景會出現,內文能不能被看清楚就不是很大的重點。(os.當初看到範例時還以為是什麼解謎遊戲呢)

Brush還能用在哪些地方?


任何有用到 TextStyle 參數或是AnnotatedString的元件 (components) 都可以使用自定義的筆刷。
例如 TextField 輸入的字體也可以動態上色。

https://ithelp.ithome.com.tw/upload/images/20220920/20136048vRougThtrK.png

@OptIn(ExperimentalMaterial3Api::class, ExperimentalTextApi::class)
@Preview()
@Composable
fun MyBrushTextField() {
    var text by remember { mutableStateOf("") } //1.
    val brush = remember {
        Brush.linearGradient(
            colors = RainbowColors
        )
    }
    KTheme() {
        TextField(
            modifier = Modifier.padding(8.dp),
            value = text,
            onValueChange = { text = it },
            textStyle = TextStyle(brush = brush) //2.
        )
    }
}
  1. remember 把筆刷brush記住之外,記得也要把輸入的字text記住。
  2. 將定義好的筆刷傳入 TextStyle 的參數 brush

從圖片來看顏色是以一行作為單位渲染,如果TextFiled 的寬度變動,顏色渲染也會跟著更新。
我用的彩虹色組,很適合深色模式,用起來很像 Ig 風。

只讓重點字串改顏色 AnnotatedString


除了整片文字,我們也可以只讓一句話套用筆刷風格。
這裡我們用土味情話來當作例文。

https://ithelp.ithome.com.tw/upload/images/20220920/20136048ybROhmmQYE.png

我們可以用 AnnotatedString 把字段用 append 來連結,append 外圍用 withStyle 包起來套用想要的字體屬性,withStyle 的參數中使用 SpanStylebrush 給傳進去。

@OptIn(ExperimentalTextApi::class)
@Preview(showBackground = true)
@Composable
fun AnnotatedString() {
    KTheme(darkTheme = true) {
        Text(
            buildAnnotatedString {
                append("小明:剛剛下雨了嗎?\n")
                append("小美:沒有啊\n")
                withStyle(
                    SpanStyle(
                        brush = Brush.linearGradient(
                            colors = RainbowColors
                        )
                    )
                ) {
                    append("小明:那為什麼你的臉上會有彩虹啊?")
                }
            }
        )
    }
}

透明度(Opacity)

https://ithelp.ithome.com.tw/upload/images/20220920/20136048B4KT1ByWPu.png

字段除了把顏色帶入,還可以調透明度。SpanStyle 帶入參數 alphaalpha 值介於 0f~1f(全透明~實色。透明度 50% 可以用0.5f 或省略成 .5f 來表示。

@OptIn(ExperimentalTextApi::class)
@Preview
@Composable
fun OpacityWithBrush() {
    val brush = Brush.linearGradient(colors = RainbowColors)
    Text(
        buildAnnotatedString {
            withStyle(
                SpanStyle(
                    brush = brush,
                    alpha = .5f
                )
            ) {
                append("Text in ")
            }
            withStyle(
                SpanStyle(
                    brush = brush,
                    alpha = 1f
                )
            ) {
                append("Compose ❤️")
            }
        }
    )
}

總結


我們用了筆刷來改變字體顏色。筆刷顏色可以來自 List<Color> 或圖片。筆刷也能作為 Style 傳入有brush 參數的地方,來達到局部字體套用 Style 的效果。

參考


Brushing up on Compose Text coloring

今日運動
感冒快好了 拉筋


上一篇
Day 13 Text Brush
下一篇
Day 15 Lazy Grid Layout
系列文
今年一定減成功!Jetpack Compose 做出重訓紀錄APP30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
John Lu
iT邦新手 4 級 ‧ 2022-09-21 00:07:05

ShaderBrush 很讚

我要留言

立即登入留言