Brush
di Compose menjelaskan cara menggambar sesuatu di layar: menentukan
warna yang digambar di area gambar (misalnya lingkaran,
persegi, jalur). Ada beberapa Kuas bawaan yang berguna untuk menggambar,
seperti LinearGradient
, RadialGradient
, atau kuas
SolidColor
biasa.
Kuas dapat digunakan dengan panggilan gambar Modifier.background()
, TextStyle
, atau
DrawScope
untuk menerapkan gaya gambar ke konten
yang digambar.
Misalnya, kuas gradien horizontal dapat diterapkan untuk menggambar lingkaran di
DrawScope
:
val brush = Brush.horizontalGradient(listOf(Color.Red, Color.Blue)) Canvas( modifier = Modifier.size(200.dp), onDraw = { drawCircle(brush) } )
Kuas gradien
Ada banyak kuas gradien bawaan yang dapat digunakan untuk mendapatkan efek gradien yang berbeda. Kuas ini memungkinkan Anda menentukan daftar warna yang ingin Anda buatkan gradiennya.
Daftar kuas gradien yang tersedia dan outputnya yang sesuai:
Jenis Kuas Gradien | Output |
---|---|
Brush.horizontalGradient(colorList) |
|
Brush.linearGradient(colorList) |
|
Brush.verticalGradient(colorList) |
|
Brush.sweepGradient(colorList)
Catatan: Untuk mendapatkan transisi yang lancar antar-warna, tetapkan warna terakhir ke warna awal. |
|
Brush.radialGradient(colorList) |
Mengubah distribusi warna dengan colorStops
Untuk menyesuaikan tampilan warna dalam gradien, Anda dapat menyesuaikan nilai
colorStops
untuk setiap warna. colorStops
harus ditentukan sebagai pecahan,
antara 0 dan 1. Nilai yang lebih besar dari 1 akan menyebabkan warna tersebut tidak dirender
sebagai bagian dari gradien.
Anda dapat mengonfigurasi perhentian warna agar memiliki jumlah yang berbeda, seperti lebih sedikit atau lebih banyak dari warna tertentu:
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)) )
Warna tersebar pada offset yang diberikan seperti yang ditentukan dalam pasangan colorStop
,
agak lebih kuning daripada merah dan biru.
Mengulang pola dengan TileMode
Setiap kuas gradien memiliki opsi untuk menyetel TileMode
di atasnya. Anda mungkin tidak
melihat TileMode
jika belum menyetel awal dan akhir gradien, karena
defaultnya adalah untuk mengisi seluruh area. TileMode
hanya akan membuat kotak gradien
jika ukuran area lebih besar dari ukuran Kuas.
Kode berikut akan mengulangi pola gradien 4 kali, karena endX
disetel ke
50.dp
dan ukurannya disetel ke 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 ) ) )
Berikut adalah tabel yang menjelaskan fungsi Mode Kotak yang berbeda untuk
contoh HorizontalGradient
di atas:
TileMode | Output |
---|---|
TileMode.Repeated : Tepi diulang dari warna terakhir ke pertama. |
|
TileMode.Mirror : Tepi dicerminkan dari warna terakhir ke pertama. |
|
TileMode.Clamp : Tepi dibatasi ke warna akhir. Langkah ini akan menampilkan warna terdekat untuk wilayah lainnya. |
|
TileMode.Decal : Hanya merender hingga ukuran batas. TileMode.Decal memanfaatkan warna hitam transparan untuk mengambil sampel konten di luar batas asli sedangkan TileMode.Clamp mengambil sampel warna tepi. |
TileMode
berfungsi dengan cara yang sama untuk gradien arah lainnya,
yang berbeda adalah arah pengulangannya.
Mengubah Ukuran kuas
Jika mengetahui ukuran area tempat kuas akan digambar, Anda dapat
menyetel kotak endX
seperti yang telah kita lihat di atas, di bagian TileMode
. Jika berada dalam
DrawScope
, Anda dapat menggunakan properti size
untuk mendapatkan ukuran area tersebut.
Jika tidak tahu ukuran area gambar (misalnya, jika
Brush
ditetapkan ke Teks), Anda dapat memperluas Shader
dan memanfaatkan ukuran
area gambar di fungsi createShader
.
Dalam contoh ini, bagi ukuran dengan 4 untuk mengulangi pola 4 kali:
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) )
Anda juga dapat mengubah ukuran kuas gradien lainnya, seperti gradien
radial. Jika Anda tidak menentukan ukuran dan pusat, gradien akan menempati
batas penuh DrawScope
, dan pusat gradien radial akan disetel default
ke pusat batas DrawScope
. Hal ini menyebabkan pusat gradien
radial muncul sebagai pusat dimensi yang lebih kecil (lebar atau
tinggi):
Box( modifier = Modifier .fillMaxSize() .background( Brush.radialGradient( listOf(Color(0xFF2be4dc), Color(0xFF243484)) ) ) )
Ketika gradien radial diubah untuk menetapkan ukuran radius ke dimensi maksimum, Anda dapat melihat bahwa gradien menghasilkan efek gradien radial yang lebih baik:
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) )
Perlu diperhatikan bahwa ukuran sebenarnya yang diteruskan ke pembuatan shader
ditentukan dari tempat pemanggilannya. Secara default, Brush
akan mengalokasikan ulang Shader
secara internal jika ukurannya berbeda
dengan pembuatan
Brush
terakhir, atau jika objek status yang digunakan dalam pembuatan shader telah
berubah.
Kode berikut membuat shader dengan tiga waktu yang berbeda dengan ukuran yang berbeda, karena ukuran area gambar berubah:
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) } } } )
Menggunakan gambar sebagai kuas
Untuk menggunakan ImageBitmap sebagai Brush
, muat gambar sebagai ImageBitmap
,
lalu buat kuas 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))
Kuas diterapkan ke beberapa jenis gambar: latar belakang, Teks, dan Kanvas. Tindakan ini menghasilkan hal berikut:
Perhatikan bahwa teks kini juga dirender menggunakan ImageBitmap
guna menggambar
piksel untuk teks.
Contoh lanjutan: Kuas kustom
Kuas RuntimeShader
AGSL
AGSL menawarkan subset kemampuan Shader GLSL. Shader dapat ditulis dalam AGSL dan digunakan dengan Kuas di Compose.
Untuk membuat kuas Shader, tentukan terlebih dahulu string shader 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()
Shader di atas mengambil dua warna input, menghitung jarak dari kiri
bawah (vec2(0, 1)
) area gambar dan melakukan mix
di antara dua warna
berdasarkan jaraknya. Tindakan ini akan menghasilkan efek gradien.
Kemudian, buat Kuas Shader, dan setel seragam untuk resolution
- ukuran
area gambar, serta color
dan color2
yang ingin Anda gunakan sebagai input untuk
gradien kustom:
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) ) }
Dengan menjalankan ini, Anda dapat melihat hal berikut dirender di layar:
Perlu diperhatikan bahwa Anda dapat melakukan lebih banyak hal dengan shader, bukan hanya gradien, karena semuanya merupakan penghitungan berbasis matematika. Untuk informasi selengkapnya tentang AGSL, lihat dokumentasi AGSL.
Referensi lainnya
Untuk contoh selengkapnya tentang penggunaan Kuas di Compose, lihat referensi berikut:
- Menganimasikan warna Teks kuas di Compose 🖌️
- Grafik dan Tata Letak Kustom di Compose - Android Dev Summit 2022
- Contoh JetLagged - Kuas RuntimeShader
Direkomendasikan untuk Anda
- Catatan: teks link ditampilkan saat JavaScript nonaktif
- Pengubah Grafik
- Grafik di Compose
- Memberi gaya pada teks