يصف Brush
في Compose طريقة رسم عنصر على الشاشة، فهو يحدّد الألوان التي يتم رسمها في مساحة الرسم (مثل دائرة أو مربّع أو مسار). تتوفّر بعض الفرش المدمجة المفيدة للرسم، مثل 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
بطريقة مشابهة مع التدرّجات الاتجاهية الأخرى،
ويكمن الاختلاف في الاتجاه الذي يحدث فيه التكرار.
تغيير حجم الفرشاة
إذا كنت تعرف حجم المساحة التي سيتم الرسم فيها بالفرشاة، يمكنك ضبط المربّع endX
كما رأينا أعلاه في القسم TileMode
. إذا كنت في 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
لرسم وحدات البكسل الخاصة بالنص.
مثال متقدّم: فرشاة مخصّصة
فرشاة RuntimeShader
AGSL
توفّر AGSL مجموعة فرعية من إمكانات GLSL Shader. يمكن كتابة برامج التظليل بلغة AGSL واستخدامها مع "فرشاة" في Compose.
لإنشاء فرشاة Shader، يجب أولاً تحديد Shader كسلسلة 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()
يأخذ برنامج التظليل أعلاه لونَين كمدخلات، ويحسب المسافة من أسفل اليمين (vec2(0, 1)
) لمنطقة الرسم، ثم ينفّذ عملية mix
بين اللونَين استنادًا إلى المسافة. يؤدي ذلك إلى إنشاء تأثير تدرّج.
بعد ذلك، أنشئ Shader Brush واضبط المتغيرات الموحّدة 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، يمكنك الاطّلاع على المستندات الخاصة بها.
مراجع إضافية
لمزيد من الأمثلة حول استخدام أداة Brush في Compose، يمكنك الاطّلاع على المراجع التالية:
- إضافة حركة إلى ألوان النص باستخدام الفرشاة في Compose 🖌️
- الرسومات والتنسيقات المخصّصة في Compose - مؤتمر Android Dev Summit 2022
- JetLagged Sample - RuntimeShader Brush
أفلام مُقترَحة لك
- ملاحظة: يتم عرض نص الرابط عندما تكون JavaScript غير مفعّلة
- معدِّلات الرسومات
- الرسومات في "إنشاء"
- تنسيق النص