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