Compose-এ 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 | আউটপুট |
|---|---|
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 তৈরি করার সময়কার সাইজের থেকে আলাদা হয় অথবা শেডার তৈরি করার সময় ব্যবহৃত স্টেট অবজেক্টে
পরিবর্তন করা হলে, ডিফল্ট হিসেবে 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) } } } )
ব্রাশ হিসেবে ছবি ব্যবহার করা
Brush হিসেবে ImageBitmap ব্যবহার করতে, ছবিটিকে 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-এ ব্রাশের সাথে ব্যবহার করা যায়।
Shader ব্রাশ তৈরি করতে, প্রথমে AGSL Shader স্ট্রিং হিসেবে Shader-কে সংজ্ঞায়িত করুন:
@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 ডকুমেন্টেশন দেখুন।
অতিরিক্ত রিসোর্স
কম্পোজ উইন্ডোতে ব্রাশ ব্যবহার করার আরও উদাহরণ দেখতে, নিম্নলিখিত রিসোর্স চেক করে দেখুন:
- Compose-এ ব্রাশের মাধ্যমে টেক্সট কালারিং অ্যানিমেট করা 🖌️
- Compose-এ কাস্টম গ্রাফিক্স ও লেআউট - Android Dev Summit 2022
- JetLagged Sample - RuntimeShader Brush
আপনার জন্য সাজেস্ট করা হয়েছে
- মনে রাখবেন: জাভাস্ক্রিপ্ট বন্ধ থাকলে লিঙ্ক টেক্সট দেখানো হয়
- গ্রাফিক্স মডিফায়ার
- Compose-এ গ্রাফিক্স
- টেক্সট স্টাইল করা