Compose 中的 Brush
說明了如何在螢幕上繪圖:判斷在繪圖區域 (即圓形、正方形、路徑) 所繪製的顏色。我們提供了幾種內建的筆刷 可用於繪圖
例如 LinearGradient
、RadialGradient
或純文字
SolidColor
筆刷。
筆刷可搭配 Modifier.background()
、TextStyle
或
DrawScope
繪製呼叫,以將繪畫風格套用至內容
以及繪圖
舉例來說,您可以套用水平漸層筆刷來繪製圓形
DrawScope
:
val brush = Brush.horizontalGradient(listOf(Color.Red, Color.Blue)) Canvas( modifier = Modifier.size(200.dp), onDraw = { drawCircle(brush) } )
漸層筆刷
提供許多內建的漸層筆刷,可用於實現不同的漸層效果。這些筆刷可讓你指定偏好的顏色清單 建立漸層時
可用的漸層筆刷清單及其相應輸出:
漸層筆刷類型 | 輸出 |
---|---|
Brush.horizontalGradient(colorList) |
|
Brush.linearGradient(colorList) |
|
Brush.verticalGradient(colorList) |
|
Brush.sweepGradient(colorList) 敬上
注意:如要在各個顏色之間順暢轉換,請將最後一種顏色設定為起始顏色。 |
|
Brush.radialGradient(colorList) |
使用 colorStops
變更色彩分佈
如要自訂色彩在漸層中出現的方式,可以調整
每個變數的「colorStops
」值。colorStops
應指定為分數
介於 0 到 1 之間。如果值大於 1,則無法顯示這些顏色
您可以在顏色停止點設定不同的顏色數量,例如 我就會變換顏色
val colorStops = arrayOf( 0.0f to Color.Yellow, 0.2f to Color.Red, 1f to Color.Blue ) Box( modifier = Modifier .requiredSize(200.dp) .background(Brush.horizontalGradient(colorStops = colorStops)) )
顏色會依照 colorStop
配對中定義的補償值分散,如黃色比紅色和藍色少。
使用 TileMode
重複圖案
每種漸層筆刷都可以選擇在其上設定 TileMode
。您不得
注意,如果您尚未設定漸層的開始和結束,則會看到 TileMode
,如
系統就會根據預設填滿整個區域TileMode
只會設定漸層圖塊
區域大小超過筆刷大小時。
下列程式碼會重複漸層模式 4 次,因為 endX
是
設為 50.dp
,且大小設為 200.dp
:
val listColors = listOf(Color.Yellow, Color.Red, Color.Blue) val tileSize = with(LocalDensity.current) { 50.dp.toPx() } Box( modifier = Modifier .requiredSize(200.dp) .background( Brush.horizontalGradient( listColors, endX = tileSize, tileMode = TileMode.Repeated ) ) )
下表詳細說明瞭各種圖塊模式對
上述 HorizontalGradient
範例:
TileMode | 輸出 |
---|---|
TileMode.Repeated :邊緣從最後一種顏色重複到第一個顏色。 |
|
TileMode.Mirror :邊緣從最後一種顏色鏡像到第一種顏色。 |
|
TileMode.Clamp :邊緣被限制為最終顏色。然後對其餘區域繪製最接近的顏色。 |
|
TileMode.Decal :僅在邊界大小內呈現。TileMode.Decal 善用透明黑色,對原始邊界外的內容進行取樣,而 TileMode.Clamp 則是運用邊緣色彩進行取樣。 |
TileMode
的運作方式類似於其他定向漸層,在重複方向出現色差。
變更筆刷大小
如果您知道畫筆繪製的區域大小,可以
如上述 TileMode
部分所示,設定圖塊 endX
。如果您位於
DrawScope
,您可以使用其 size
屬性取得區域大小。
如果不知道繪製區域的大小 (例如,如果
已將 Brush
指派給文字),您可以擴充 Shader
,並使用
createShader
函式中的繪製區域。
在這個範例中,您可以將大小除以 4,藉此重複 4 次這種模式:
val listColors = listOf(Color.Yellow, Color.Red, Color.Blue) val customBrush = remember { object : ShaderBrush() { override fun createShader(size: Size): Shader { return LinearGradientShader( colors = listColors, from = Offset.Zero, to = Offset(size.width / 4f, 0f), tileMode = TileMode.Mirror ) } } } Box( modifier = Modifier .requiredSize(200.dp) .background(customBrush) )
此外,您還可以變更任何其他漸層的筆刷大小,例如放射狀
梯度如未指定尺寸和置中,則漸層會佔據
DrawScope
的完整邊界,以及放射漸層預設值的中心
到 DrawScope
邊界的中心。這樣會使放射漸層的中心以較小維度 (寬度或高度) 顯示:
Box( modifier = Modifier .fillMaxSize() .background( Brush.radialGradient( listOf(Color(0xFF2be4dc), Color(0xFF243484)) ) ) )
在變更放射漸層時,如果將半徑大小設為最大維度, 可以看到可產生更好的放射漸層效果:
val largeRadialGradient = object : ShaderBrush() { override fun createShader(size: Size): Shader { val biggerDimension = maxOf(size.height, size.width) return RadialGradientShader( colors = listOf(Color(0xFF2be4dc), Color(0xFF243484)), center = size.center, radius = biggerDimension / 2f, colorStops = listOf(0f, 0.95f) ) } } Box( modifier = Modifier .fillMaxSize() .background(largeRadialGradient) )
值得注意的是,傳遞至建立著色器的實際大小取決於叫用的位置。根據預設,Brush
會
如果大小與上一個不同,則在內部重新分配其 Shader
建立 Brush
,或建立著色器時使用的狀態物件
已變更。
下列程式碼會建立三種著色器,且不同的 此時,會隨著繪圖區域大小改變:
val colorStops = arrayOf( 0.0f to Color.Yellow, 0.2f to Color.Red, 1f to Color.Blue ) val brush = Brush.horizontalGradient(colorStops = colorStops) Box( modifier = Modifier .requiredSize(200.dp) .drawBehind { drawRect(brush = brush) // will allocate a shader to occupy the 200 x 200 dp drawing area inset(10f) { /* Will allocate a shader to occupy the 180 x 180 dp drawing area as the inset scope reduces the drawing area by 10 pixels on the left, top, right, bottom sides */ drawRect(brush = brush) inset(5f) { /* will allocate a shader to occupy the 170 x 170 dp drawing area as the inset scope reduces the drawing area by 5 pixels on the left, top, right, bottom sides */ drawRect(brush = brush) } } } )
使用圖片做為筆刷
如要使用 ImageBitmap 做為 Brush
,請將圖片載入為 ImageBitmap
。
並建立 ImageShader
筆刷:
val imageBrush = ShaderBrush(ImageShader(ImageBitmap.imageResource(id = R.drawable.dog))) // Use ImageShader Brush with background Box( modifier = Modifier .requiredSize(200.dp) .background(imageBrush) ) // Use ImageShader Brush with TextStyle Text( text = "Hello Android!", style = TextStyle( brush = imageBrush, fontWeight = FontWeight.ExtraBold, fontSize = 36.sp ) ) // Use ImageShader Brush with DrawScope#drawCircle() Canvas(onDraw = { drawCircle(imageBrush) }, modifier = Modifier.size(200.dp))
筆刷適用於多種繪圖:背景、文字 以及「畫布」這會輸出下列內容:
請注意,系統現在也會使用 ImageBitmap
轉譯文字,為
像素做為文字的依據
進階範例:自訂筆刷
AGSL RuntimeShader
筆刷
AGSL 提供部分 GLSL 著色器功能。著色器可以 以 AGSL 編寫,並在 Compose 中與筆刷搭配使用。
如要建立著色器筆刷,首先將著色器定義為 AGSL 著色器字串:
@Language("AGSL") val CUSTOM_SHADER = """ uniform float2 resolution; layout(color) uniform half4 color; layout(color) uniform half4 color2; half4 main(in float2 fragCoord) { float2 uv = fragCoord/resolution.xy; float mixValue = distance(uv, vec2(0, 1)); return mix(color, color2, mixValue); } """.trimIndent()
上方的著色器使用兩種輸入顏色,計算與底部之間的距離
繪製區域的左側 (vec2(0, 1)
),並在兩種顏色之間執行 mix
分成不同大小組合這會產生漸層效果。
接著建立著色器筆刷,並設定 resolution
的大小
以及您要做為輸入內容的 color
和 color2
自訂漸層:
val Coral = Color(0xFFF3A397) val LightYellow = Color(0xFFF8EE94) @RequiresApi(Build.VERSION_CODES.TIRAMISU) @Composable @Preview fun ShaderBrushExample() { Box( modifier = Modifier .drawWithCache { val shader = RuntimeShader(CUSTOM_SHADER) val shaderBrush = ShaderBrush(shader) shader.setFloatUniform("resolution", size.width, size.height) onDrawBehind { shader.setColorUniform( "color", android.graphics.Color.valueOf( LightYellow.red, LightYellow.green, LightYellow .blue, LightYellow.alpha ) ) shader.setColorUniform( "color2", android.graphics.Color.valueOf( Coral.red, Coral.green, Coral.blue, Coral.alpha ) ) drawRect(shaderBrush) } } .fillMaxWidth() .height(200.dp) ) }
執行完畢後,您可以看到下列顯示的內容:
值得注意的是,除了漸層之外,著色器還提供其他更多功能 因為都是以數學為基礎的運算如需進一步瞭解 AGSL,請參閱 AGSL 說明文件。
其他資源
如需更多在 Compose 中使用筆刷的範例,請參閱下列資源:
- 在 Compose 中使用動畫筆刷繪製文字顏色 🖌?
- 在 Compose 中自訂圖形和版面配置 - 2022 年 Android 開發人員高峰會
- JetLagged 範例 - RuntimeShader 筆刷
為您推薦
- 注意:系統會在 JavaScript 關閉時顯示連結文字
- 圖形修飾符
- Compose 中的圖形
- 樣式文字