يصف الرمز 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 | الإخراج |
---|---|
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) )
تجدر الإشارة إلى أنّ الحجم الفعلي الذي يتم تمريره إلى عملية إنشاءshader يتم تحديده من مكان استدعائه. بشكلٍ تلقائي، سيعيد Brush
تخصيص Shader
داخليًا إذا كان الحجم مختلفًا عن عملية
إنشاء Brush
الأخيرة، أو إذا تغيّر كائن الحالة المستخدَم في إنشاءshader.
تنشئ التعليمة البرمجية التالية مخطّط التظليل ثلاث مرات مختلفة بأحجام مختلفة، وذلك مع تغيُّر حجم مساحة الرسم:
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 غير مفعّلة.
- مُعدِّلات الرسومات
- الرسومات في ميزة "إنشاء"
- نصّ النمط