یک 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
به روشی مشابه برای سایر گرادیان های جهت کار می کند، تفاوت در جهتی است که تکرار اتفاق می افتد.
تغییر اندازه برس
اگر اندازه ناحیه ای را که قلم مو در آن کشیده می شود، می دانید، می توانید endX
کاشی را همانطور که در بالا در قسمت TileMode
دیدیم تنظیم کنید. اگر در DrawScope
هستید، می توانید از ویژگی size
آن برای بدست آوردن اندازه منطقه استفاده کنید.
اگر اندازه منطقه طراحی خود را نمی دانید (به عنوان مثال اگر Brush
به Text اختصاص داده شده است)، می توانید 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
متفاوت باشد، یا اگر یک شیء حالت استفاده شده در ایجاد سایهزن تغییر کرده باشد، 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
برای رنگ آمیزی پیکسل های متن نیز رندر می شود.
مثال پیشرفته: برس سفارشی
براش RuntimeShader
AGSL
AGSL زیر مجموعه ای از قابلیت های GLSL Shader را ارائه می دهد. Shader ها را می توان با AGSL نوشت و با Brush در Compose استفاده کرد.
برای ایجاد یک براش 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، مستندات AGSL را بررسی کنید.
منابع اضافی
برای مثالهای بیشتر از استفاده از Brush در Compose، منابع زیر را بررسی کنید:
- براش متحرک رنگ آمیزی متن در Compose 🖌️
- گرافیک و طرحبندی سفارشی در Compose - Android Dev Summit 2022
- نمونه JetLagged - RuntimeShader Brush
برای شما توصیه می شود
- توجه: وقتی جاوا اسکریپت خاموش است، متن پیوند نمایش داده می شود
- اصلاح کننده های گرافیکی
- گرافیک در Compose
- متن سبک