কম্পোজ-এর একটি 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 ০ থেকে ১-এর মধ্যে একটি ভগ্নাংশ হিসেবে উল্লেখ করতে হবে। ১-এর চেয়ে বড় মান দিলে সেই রঙগুলো গ্রেডিয়েন্টের অংশ হিসেবে রেন্ডার হবে না।
আপনি কালার স্টপগুলিতে বিভিন্ন পরিমাণ কনফিগার করতে পারেন, যেমন একটি রঙের কম বা বেশি পরিমাণ:
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 কেবল তখনই গ্রেডিয়েন্টটি টাইল করবে, যখন এলাকাটির আকার ব্রাশের আকারের চেয়ে বড় হবে।
নিম্নলিখিত কোডটি গ্রেডিয়েন্ট প্যাটার্নটি ৪ বার পুনরাবৃত্তি করবে, যেহেতু 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 একইভাবে কাজ করে, পার্থক্য শুধু পুনরাবৃত্তির দিকের ওপর নির্ভর করে।
ব্রাশের আকার পরিবর্তন করুন
আপনার ব্রাশটি যে স্থানে আঁকা হবে তার আকার যদি আপনার জানা থাকে, তাহলে আপনি TileMode অংশে দেখানো পদ্ধতি অনুযায়ী টাইলের endX সেট করতে পারেন। আপনি যদি একটি DrawScope মধ্যে থাকেন, তাহলে এলাকাটির আকার জানার জন্য এর size প্রপার্টি ব্যবহার করতে পারেন।
যদি আপনি আপনার অঙ্কন এলাকার আকার না জানেন (উদাহরণস্বরূপ, যদি Brush টেক্সট-এ নির্ধারিত থাকে), তাহলে আপনি Shader প্রসারিত করতে পারেন এবং createShader ফাংশনে অঙ্কন এলাকার আকার ব্যবহার করতে পারেন।
এই উদাহরণে, প্যাটার্নটি ৪ বার পুনরাবৃত্তি করতে আকারটিকে ৪ দিয়ে ভাগ করুন:
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 ব্যবহার করে টেক্সটটিও রেন্ডার করা হচ্ছে।
উন্নত উদাহরণ: কাস্টম ব্রাশ
AGSL RuntimeShader ব্রাশ
AGSL, GLSL- এর শেডার সক্ষমতার একটি উপসেট প্রদান করে। AGSL-এ শেডার লেখা যায় এবং Compose-এ ব্রাশের সাথে তা ব্যবহার করা যায়।
একটি শেডার ব্রাশ তৈরি করতে, প্রথমে শেডারটিকে 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 ডকুমেন্টেশন দেখুন।
অতিরিক্ত সম্পদ
কম্পোজে ব্রাশ ব্যবহারের আরও উদাহরণের জন্য, নিম্নলিখিত রিসোর্সগুলো দেখুন:
- কম্পোজে ব্রাশ দিয়ে টেক্সট কালারিং অ্যানিমেট করা 🖌️
- কম্পোজে কাস্টম গ্রাফিক্স ও লেআউট - অ্যান্ড্রয়েড ডেভ সামিট ২০২২
- JetLagged নমুনা - রানটাইমশেডার ব্রাশ
আপনার জন্য প্রস্তাবিত
- দ্রষ্টব্য: জাভাস্ক্রিপ্ট বন্ধ থাকলেও লিঙ্কের লেখা প্রদর্শিত হয়।
- গ্রাফিক্স মডিফায়ার
- কম্পোজে গ্রাফিক্স
- স্টাইল টেক্সট







