Paint Android Canvas-এ গ্রাফিক্স স্টাইল করার প্রধান ক্লাস। এটি ইউজার ইন্টারফেসের সমস্ত অঙ্কন অপারেশনের জন্য রং, লাইনের পুরুত্ব, ফিল স্টাইল, ব্লার ইফেক্ট ও ফন্ট নির্ধারণ করে। Paint ছাড়া Canvas প্রদর্শিত উপাদানগুলিতে ভিজ্যুয়াল অ্যাট্রিবিউট প্রয়োগ করতে পারে না। Google Developers, 2026-এর তথ্য অনুযায়ী, Paint গ্র্যাডিয়েন্ট ও টেক্সচারসহ 42টি পর্যন্ত স্টাইল প্যারামিটার সমর্থন করে।
মূল বিষয়
Paint হলো android.graphics প্যাকেজের একটি ক্লাস যা Canvas-এ অঙ্কন অপারেশনের জন্য সমস্ত স্টাইল সেটিং সংরক্ষণ করে। এতে নিজে পিক্সেল থাকে না, বরং নির্ধারণ করে লাইন, আকার ও টেক্সট ঠিক কেমন দেখাবে। Canvas পদ্ধতির প্রতিটি কল — drawCircle, drawLine, drawText — ভিজ্যুয়াল উপস্থাপনা ব্যাখ্যা করতে Paint ব্যবহার করে।
Paint কনফিগারেশন অবজেক্টের নীতি অনুযায়ী কাজ করে। আপনি একটি ইনস্ট্যান্স তৈরি করেন, প্যারামিটারগুলো একবার সেট করেন এবং সেটিকে অনেক অপারেশনে পুনরায় ব্যবহার করেন। এটি অঙ্কন লুপে অ্যালোকেশনের সংখ্যা কমিয়ে দেয় এবং প্রতি ফ্রেমে নতুন অবজেক্ট তৈরির তুলনায় পারফরম্যান্স 30% পর্যন্ত বাড়ায়। Google I/O 2024-এর তথ্য অনুযায়ী, কাস্টম গ্রাফিক্সে 60 FPS অর্জনের জন্য Paint-এর অপটিমাইজেশন অন্যতম গুরুত্বপূর্ণ অনুশীলন।
Paint-এর সমস্ত সেটিং কয়েকটি বিভাগে ভাগ করা হয়: রং ও স্বচ্ছতা, স্ট্রোক ও ফিল স্টাইল, টেক্সট ও ফন্ট নিয়ে কাজ, ব্লার ও মাস্কিং ইফেক্ট। প্রতিটি বিভাগ আলাদা সেটার পদ্ধতি দ্বারা নিয়ন্ত্রিত হয় যা যেকোনো সমন্বয়ে মেশানো যায়। এটি Paint API-কে নমনীয় করে, কিন্তু প্যারামিটারগুলির পারস্পরিক সম্পর্ক বোঝার প্রয়োজন হয় — যেমন, Style নির্ধারণ করে Shader কনট্যুরে না ফিলে প্রয়োগ হবে।
setColor পরবর্তী সমস্ত অঙ্কন অপারেশনের জন্য রং নির্ধারণের প্রধান পদ্ধতি। রং ARGB ফরম্যাটে (32-বিট পূর্ণসংখ্যা) পাঠানো হয়, যেখানে উপরের 8 বিট আলফা-চ্যানেল এবং বাকিগুলো লাল, সবুজ ও নীল চ্যানেল। 0xFF0000FF মানটি অস্বচ্ছ নীল রং সেট করে।
পদ্ধতি setAlpha 0 (সম্পূর্ণ স্বচ্ছ) থেকে 255 (সম্পূর্ণ অস্বচ্ছ) সীমার মধ্যে স্বাধীনভাবে স্বচ্ছতা নিয়ন্ত্রণের সুযোগ দেয়। setColor-এ আলফা নির্দিষ্ট করার বিপরীতে এই পদ্ধতি আগে সেট করা রংয়ের টোনকে প্রভাবিত করে না — এটি কেবল সামগ্রিক স্বচ্ছতা নিয়ন্ত্রণ করে। রং পরিবর্তন না করেই উপাদানের আবির্ভাব ও অদৃশ্য হওয়ার অ্যানিমেশনের জন্য এটি সুবিধাজনক।
ColorFilter অঙ্কনের আগে প্রতিটি পিক্সেলের রং রূপান্তরের একটি প্রক্রিয়া। তিনটি মোড সমর্থিত: চ্যানেল গুণ ও যোগের জন্য LightingColorFilter, ব্লেন্ডিং মোড ব্যবহারকারী PorterDuffColorFilter এবং পূর্ণাঙ্গ ম্যাট্রিক্স রূপান্তরের জন্য ColorMatrixColorFilter। ColorFilter Shader-এর পরে কিন্তু Canvas-এ আউটপুটের আগে প্রয়োগ হয়।
বেশিরভাগ কাজের জন্য স্ট্যান্ডার্ড setColor বা setAlpha যথেষ্ট। ColorFilter মূলত ডিস্যাচুরেশন, সেপিয়া বা ইনভারশন ইফেক্টের জন্য ব্যবহৃত হয়। ColorFilter প্রয়োগ GPU-র বোঝা বাড়ায়, তাই Google onDraw-এর লুপ কলগুলিতে এর ব্যবহার কমানোর পরামর্শ দেয়।
| পদ্ধতি | বর্ণনা | পারফরম্যান্স |
|---|---|---|
| setColor | ARGB-তে রং নির্ধারণ করে | O(1) — কোনো ওভারহেড নেই |
| setAlpha | স্বচ্ছতা (0-255) নিয়ন্ত্রণ করে | O(1) — হালকা অপারেশন |
| setColorFilter | রং সংশোধন প্রয়োগ করে | O(n) — বারবার কল করলে FPS-কে প্রভাবিত করে |
পদ্ধতি setStyle Paint.Style-এর তিনটি মানের একটি গ্রহণ করে: FILL (ফিল), STROKE (কনট্যুর) বা FILL_AND_STROKE (দুইটিই একসাথে)। স্টাইল নির্বাচনের উপর নির্ভর করে আকারটি সিলুয়েট, কাঠামো বা ভেতরে ফিলসহ কনট্যুর হিসেবে দেখানো হবে। ডিফল্টভাবে Paint FILL স্টাইল দিয়ে তৈরি হয়।
setStrokeWidth STROKE মোডের জন্য পিক্সেলে লাইনের পুরুত্ব নির্ধারণ করে। গোল আকার ও গোলাকার কোণের জন্য setStrokeCap (Cap.ROUND, BUTT, SQUARE) এবং setStrokeJoin (Join.MITER, ROUND, BEVEL) ব্যবহৃত হয়। এই প্যারামিটারগুলো কাস্টম View-এ গ্রাফ, পাথ ও ফ্রেমের চেহারায় গুরুত্বপূর্ণ প্রভাব ফেলে।
১ পিক্সেলের কম পুরুত্বে লাইনটি সাবপিক্সেল নির্ভুলতায় আঁকা হয়, কিন্তু কম ঘনত্বের স্ক্রিনে ঝাপসা দেখাতে পারে। Android-এর রেটিনা-ডিসপ্লের জন্য dp-কে পিক্সেলে রূপান্তর করতে TypedValue.applyDimension ব্যবহার করুন। 2 dp পুরুত্ব বেশিরভাগ ডিভাইসে স্পষ্ট দৃশ্যমানতা নিশ্চিত করে।
DashPathEffect ড্যাশযুক্ত ও ড্যাশ-বিন্দুযুক্ত লাইন তৈরি করে। কনস্ট্রাক্টর পর্যায়ক্রমিক ড্যাশ ও ফাঁকের দৈর্ঘ্যের একটি অ্যারে এবং প্রাথমিক ফেজ অফসেট গ্রহণ করে। যেমন, অ্যারে [10, 5, 3, 5] লম্বা ড্যাশ, ছোট ফাঁক, ছোট ড্যাশ ও ফাঁকসহ একটি লাইন তৈরি করে। এই ইফেক্ট গ্রাফিক্স এডিটর ও অ্যানোটেশন টুলে সক্রিয়ভাবে ব্যবহৃত হয়।
স্টাইলগুলির সংমিশ্রণ setPathEffect-এর মাধ্যমে হয়। CornerPathEffect, DashPathEffect ও DiscretePathEffect একত্রিত করে ডায়াগ্রাম, ক্যাপশন ও সাজসজ্জা উপাদানের জন্য জটিল ভিজ্যুয়াল লাইন তৈরি করা যায়। প্রতিটি PathEffect CPU-তে গণনা করা হয়, তাই অনেক লাইন বিশিষ্ট অ্যানিমেশনে ইফেক্টটি আগে থেকে Bitmap-এ রাস্টারাইজ করার পরামর্শ দেওয়া হয়।
val paint = Paint().apply {
setStyle(Paint.Style.STROKE)
setStrokeWidth(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2f, resources.displayMetrics))
setPathEffect(DashPathEffect(floatArrayOf(10f, 5f, 3f, 5f), 0f))
}
Typeface একটি অবজেক্ট যা Paint-এর সমস্ত টেক্সট অপারেশনের জন্য ফন্টের গার্নিচার নির্ধারণ করে। Android সিস্টেম ফন্ট (Roboto, Noto Sans), assets রিসোর্সের কাস্টম ফন্ট এবং Downloadable Fonts API-র মাধ্যমে লোডযোগ্য ফন্ট সমর্থন করে। Typeface ইনস্টল করা হয় Paint ইনস্ট্যান্সে setTypeface-এর মাধ্যমে।
পদ্ধতি setTextSize পিক্সেলে ফন্টের আকার নির্ধারণ করে। বিভিন্ন স্ক্রিনে সঠিক প্রদর্শনের জন্য TypedValue.applyDimension ব্যবহার করে sp-এ আকার নির্ধারণের পরামর্শ দেওয়া হয়। লাইনের ব্যবধান অনুভূমিক প্রসারণের জন্য setTextScaleX দ্বারা নিয়ন্ত্রিত হয় এবং Canvas.drawText-এর মাধ্যমে বহু-লাইন টেক্সটের অন্তর্নির্মিত সমর্থনে অন্তর্ভুক্ত হয়।
টেক্সট সাজানোর জন্য setTextAlign ব্যবহার করা হয় LEFT, CENTER ও RIGHT মানসহ। CENTER-এ drawText-এ পাঠানো x স্থানাঙ্ক টেক্সটের কেন্দ্রবিন্দু হয়ে যায় — এটি আইকনের নিচের ক্যাপশন ও আকারের ভেতরের শিরোনামের জন্য বিশেষভাবে সুবিধাজনক। সঠিক অবস্থানের জন্য measureText ও getTextBounds পদ্ধতি ব্যবহার করা হয়, যা টেক্সটের প্রস্থ ও সীমানা আয়তক্ষেত্র প্রদান করে।
setUnderlineText এবং setStrikeThruText যথাক্রমে আন্ডারলাইন ও স্ট্রাইকথ্রু সক্ষম করে। এই প্যারামিটারগুলো গার্নিচার স্তরে কাজ করে এবং এই Paint দিয়ে আঁকা সমস্ত টেক্সটে প্রয়োগ হয়। একই স্ট্রিংয়ের বিভিন্ন অংশের নমনীয় ফরম্যাটিংয়ের জন্য আলাদা সেটিংসহ আলাদা Paint অবজেক্ট ব্যবহার করুন বা drawText কলের মধ্যে প্যারামিটার পরিবর্তন করুন।
| পদ্ধতি | উদ্দেশ্য | পরিমাপের একক |
|---|---|---|
| setTextSize | ফন্টের আকার | px (পিক্সেল) |
| setTextAlign | অনুভূমিক সাজানো | LEFT, CENTER, RIGHT |
| setTypeface | ফন্টের গার্নিচার | Typeface object |
| setUnderlineText | আন্ডারলাইন | Boolean |
Shader গ্র্যাডিয়েন্ট, রাস্টার টেক্সচার ও কম্পোজিটিং দিয়ে আকার ভরাটের জন্য ভিত্তি ক্লাস। setShader পদ্ধতির মাধ্যমে যেকোনো উপশ্রেণি নিয়োগ করা যায়: LinearGradient, RadialGradient, SweepGradient, BitmapShader বা ComposeShader। Shader setColor-এ সেট করা রংকে প্রতিস্থাপন করে এবং সমস্ত আঁকা উপাদানে প্রয়োগ হয়।
LinearGradient সরলরেখা বরাবর দুই বা ততোধিক রঙের মধ্যে মসৃণ রূপান্তর তৈরি করে। কনস্ট্রাক্টর শুরুর ও শেষের বিন্দু, রঙের অ্যারে এবং তাদের অবস্থান (tile mode) গ্রহণ করে। Tile mode গ্র্যাডিয়েন্টের সীমানার বাইরের আচরণ নির্ধারণ করে: CLAMP (শেষ রঙের পুনরাবৃত্তি), MIRROR (প্রতিফলন) বা REPEAT (পুনরাবৃত্তি)। LinearGradient ব্যাকগ্রাউন্ড ফিল ও প্রগ্রেস-বারের জন্য সক্রিয়ভাবে ব্যবহৃত হয়।
RadialGradient কেন্দ্র থেকে প্রান্ত পর্যন্ত বৃত্তাকার গ্র্যাডিয়েন্ট তৈরি করে। কেন্দ্র স্থানাঙ্ক দ্বারা নির্ধারিত হয়, ব্যাসার্ধ রং পরিবর্তনের অঞ্চল নির্ধারণ করে। রেডিয়াল গ্র্যাডিয়েন্টের চেহারা বিন্দু উৎস থেকে আলোর মতো — এটি প্রায়শই বাটনের আভা ও সক্রিয় উপাদানের হাইলাইট অনুকরণে ব্যবহৃত হয়।
BlurMaskFilter আঁকা উপাদানের চারপাশে ব্লার ইফেক্ট যোগ করে। কনস্ট্রাক্টর ব্লার ব্যাসার্ধ ও স্টাইল গ্রহণ করে: NORMAL (সব দিকে ব্লার), INNER (শুধু আকারের ভেতরে), OUTER (শুধু বাইরে) এবং SOLID (আকার + বাইরের ব্লার)। BlurMaskFilter সব ধরনের Paint-এর সাথে কাজ করে এবং প্রায়শই ছায়া ও আভা ইফেক্ট তৈরিতে ব্যবহৃত হয়।
val paint = Paint().apply {
setShader(LinearGradient(
0f, 0f, width, height,
intArrayOf(Color.RED, Color.BLUE),
null,
Shader.TileMode.CLAMP
))
setMaskFilter(BlurMaskFilter(20f, BlurMaskFilter.Blur.NORMAL))
}
একটি কাস্টম View-এর পূর্ণাঙ্গ উদাহরণ দেখি যা গ্র্যাডিয়েন্ট ফিল ও টেক্সট ক্যাপশনসহ একটি বৃত্ত আঁকে। Paint ও Canvas-এর সংমিশ্রণ ন্যূনতম কোডে জটিল গ্রাফিক্স তৈরি করতে দেয়। পারফরম্যান্সের জন্য সমস্ত সেটিং ইনিশিয়ালাইজেশনে রাখা হয়েছে।
class GradientCircleView@JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : View(context, attrs) {
private val fillPaint = Paint().apply {
setShader(RadialGradient(
0f, 0f, 200f,
intArrayOf(Color.CYAN, Color.DKGRAY),
null, Shader.TileMode.CLAMP
))
}
private val textPaint = Paint().apply {
setColor(Color.WHITE)
setTextSize(TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 24f, resources.displayMetrics
))
setTextAlign(Paint.Align.CENTER)
setMaskFilter(BlurMaskFilter(5f, BlurMaskFilter.Blur.NORMAL))
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.drawCircle(200f, 200f, 150f, fillPaint)
canvas.drawText("Gradient", 200f, 210f, textPaint)
}
}
কোডে দুটি আলাদা Paint অবজেক্ট ব্যবহৃত হয়েছে: একটি রেডিয়াল গ্র্যাডিয়েন্ট দিয়ে বৃত্ত ভরাটের জন্য, অন্যটি BlurMaskFilter-এর মাধ্যমে ছায়াসহ টেক্সটের জন্য। এই বিভাজন প্যারামিটার আলাদাভাবে সেট করা এবং বিভিন্ন ধরনের উপাদান আঁকার মধ্যে Paint-এর অবস্থা রিসেট এড়ানোর সুযোগ দেয়। পারফরম্যান্স বাড়ানোর জন্য দুটি Paint-ই onDraw-তে নয়, কনস্ট্রাক্টরে তৈরি হয়।
বিভিন্ন পিক্সেল ঘনত্বের ডিভাইসে স্কেলিংয়ের সময় আকারের মানগুলোকে TypedValue.applyDimension-এর মাধ্যমে পুনরায় গণনা করতে হবে। এটি ছাড়া টেক্সট ও গ্র্যাডিয়েন্ট mdpi ও xxxhdpi স্ক্রিনে আলাদা দেখাবে। উদাহরণে টেক্সটের আকার sp-এ নির্ধারিত, যা ব্যবহারকারীর ফন্ট-আকার সিস্টেম সেটিং অনুযায়ী স্বয়ংক্রিয়ভাবে মানিয়ে নেয়।
সাধারণ প্রশ্নোত্তর
Canvas অঙ্কন অপারেশন (drawCircle, drawLine) করে, আর Paint স্টাইল — রং, পুরুত্ব, ফন্ট নির্ধারণ করে। Canvas-এ স্টাইল সেটিং থাকে না, তাই Paint ছাড়া যেকোনো অঙ্কন অপারেশনের কোনো ভিজ্যুয়াল প্রভাব থাকে না।
হ্যাঁ, একটি Paint অবজেক্ট অনেক আকারের জন্য পুনরায় ব্যবহার করা যায়। বিভিন্ন ধরনের উপাদানের (ব্যাকগ্রাউন্ড, টেক্সট, কনট্যুর) জন্য আলাদা Paint তৈরি করার পরামর্শ দেওয়া হয়, কিন্তু প্রতিটি আকারের জন্য নয় — এটি গার্বেজ কালেক্টরের বোঝা কমায়।
পদ্ধতি reset Paint-কে নতুন ইনস্ট্যান্সের সমতুল্য অবস্থায় ফিরিয়ে আনে। বিকল্পভাবে ফ্ল্যাগসহ set ব্যবহার করা যেতে পারে, তবে কোডের পঠনযোগ্যতার জন্য reset-ই উত্তম। রিসেটের পর সমস্ত স্টাইল প্যারামিটার ডিফল্ট মান গ্রহণ করে।
onDraw-এর ভেতরে Paint তৈরি প্রতিটি ফ্রেমে অ্যালোকেশনের কারণ হয়ে GC-ফ্রিজ সৃষ্টি করে। সমস্ত Paint অবজেক্ট View-এর কনস্ট্রাক্টরে তৈরি হওয়া উচিত। onDraw-তে সেটারের মাধ্যমে প্যারামিটার পরিবর্তন করা নিরাপদ এবং নতুন অবজেক্ট তৈরি করে না।
Android-এ টেক্সট সবসময় স্বচ্ছ ব্যাকগ্রাউন্ডসহ আঁকা হয়। পদ্ধতি drawText শুধু গ্লিফ আউটপুট করে, ব্যাকগ্রাউন্ড আয়তক্ষেত্র ছাড়া। যদি টেক্সটের নিচে ব্যাকগ্রাউন্ড প্রয়োজন হয়, প্রথমে আলাদা Paint দিয়ে drawRoundRect-এর মাধ্যমে আয়তক্ষেত্র আঁকুন, তারপর টেক্সট।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন