কাস্টম ভিউ যেকোনো মোবাইল অ্যাপ্লিকেশনের অনন্য ইন্টারফেসের ভিত্তি। মোবাইল অ্যাপ্লিকেশনে কাস্টম ভিউ আপনাকে নিজস্ব গ্রাফিক্স, অ্যানিমেশন এবং স্ট্যান্ডার্ড কম্পোনেন্টে অনুপলব্ধ এলিমেন্ট তৈরি করতে দেয়। Apple Developer, 2025 অনুসারে, iOS মোবাইল ডেভেলপমেন্টে drawRect কাস্টম অঙ্কনের প্রধান পদ্ধতি হিসেবে রয়ে গেছে। Android-এ, Canvas-এর সাথে onDraw একই ভূমিকা পালন করে, এবং Flutter-এ — CustomPainter।
মূল বিষয়
কাস্টম ভিউ হল ব্যবহারকারী-সংজ্ঞায়িত ইন্টারফেস কম্পোনেন্ট যা অনন্য গ্রাফিক্স তৈরি করতে স্ট্যান্ডার্ড অঙ্কন এবং মাপন পদ্ধতি ওভাররাইড করে। গ্রাফ, অ্যানিমেশন, ডায়াগ্রাম, কাস্টম চ্যাট এলিমেন্ট এবং AR মাস্ক — মোবাইল অ্যাপ্লিকেশনে কাস্টম ভিউ-এর সাধারণ ব্যবহারের ক্ষেত্র। স্ট্যান্ডার্ড UI কম্পোনেন্ট (Button, TextView, Label) ৮০% কাজ কভার করে, কিন্তু বাকি ২০% মোবাইল ডেভেলপমেন্টে অঙ্কনের উপর সম্পূর্ণ নিয়ন্ত্রণ প্রয়োজন। মোবাইল ডেভেলপমেন্টে অঙ্কন এমন একটি দক্ষতা যা জুনিয়র ডেভেলপারকে সিনিয়র থেকে আলাদা করে।
মোবাইল অ্যাপ্লিকেশনে কাস্টম ভিউ অনন্য 2D গ্রাফিক্স, জটিল অ্যানিমেশন, চার্ট এবং ডেটা ভিজুয়ালাইজেশনের জন্য প্রয়োজন। যদি স্ট্যান্ডার্ড UIKit প্রয়োজনীয় এলিমেন্ট না দেয় — তাহলে একটি কাস্টম ভিউ তৈরি করা হয়। মোবাইল অ্যাপ্লিকেশনে, কাস্টম ভিউ প্রোগ্রেস বার, কাস্টম বাটন, গ্রেডিয়েন্ট ফিল, অ্যানিমেটেড আইকন এবং আঙুল দিয়ে অঙ্কনের জন্য ক্যানভাস-এ ব্যবহৃত হয়। অতিরিক্ত ব্যবহার না করা গুরুত্বপূর্ণ — সহজ স্টাইলের জন্য, Appearance API-এর মাধ্যমে স্ট্যান্ডার্ড কম্পোনেন্ট কনফিগার করাই যথেষ্ট।
iOS-এ, কাস্টম ভিউ UIView থেকে ইনহেরিট করে এবং drawRect পদ্ধতি ওভাররাইড করে তৈরি করা হয়। drawRect প্রথম রেন্ডারে এবং প্রতিটি setNeedsDisplay() কলের পরে কল করা হয়। drawRect-এর ভিতরে, ডেভেলপার UIGraphicsGetCurrentContext()-এর মাধ্যমে CGContext পায় — লাইন, আকার, গ্রেডিয়েন্ট এবং টেক্সটের জন্য একটি ক্যানভাস। Core Graphics (Quartz 2D) একটি নিম্ন-স্তরের CPU-ভিত্তিক রেন্ডারিং ইঞ্জিন যা প্রতিটি পিক্সেলের উপর সম্পূর্ণ নিয়ন্ত্রণ দেয়। UIBezierPath সংক্ষিপ্ত সিনট্যাক্স সহ পাথ তৈরি করার জন্য একটি সুবিধাজনক র্যাপার।
class CircleView: UIView {
private var fillColor: UIColor = .systemBlue
override func drawRect(_ rect: CGRect) {
guard let ctx = UIGraphicsGetCurrentContext() else { return }
ctx.setFillColor(fillColor.cgColor)
ctx.addEllipse(in: bounds.insetBy(dx: 4, dy: 4))
ctx.drawPath(using: .fill)
}
func updateColor(_ newColor: UIColor) {
fillColor = newColor
setNeedsDisplay()
}
}
Core Graphics সব অঙ্কন অপারেশনের জন্য CGContext — একটি ক্যানভাস প্রদান করে। CGGradient CGColorSpace (sRGB, Display P3) সমর্থন সহ লিনিয়ার এবং রেডিয়াল গ্রেডিয়েন্ট তৈরি করে। ট্রান্সফর্মেশন CGAffineTransform-এর মাধ্যমে করা হয় — রোটেশন, স্কেলিং এবং ট্রান্সলেশনের জন্য 3x3 ম্যাট্রিক্স। CGContextTranslateCTM, CGContextRotateCTM এবং CGContextScaleCTM কোঅর্ডিনেট সিস্টেম পরিবর্তন করে। Core Graphics CPU-তে চলে, তাই জটিল গ্রাফিক্স প্রসেসর লোড করতে পারে — GPU ত্বরণের জন্য Metal ব্যবহার করুন।
UIBezierPath CGPath-এর উপর একটি অবজেক্ট-ওরিয়েন্টেড র্যাপার। addArc(withCenter:radius:startAngle:endAngle:clockwise:) পদ্ধতি চাপ এবং বৃত্ত তৈরি করে, addCurve Bézier বক্ররেখা তৈরি করে। পাথ addClip-এর মাধ্যমে ইউনিয়ন, ইন্টারসেকশন এবং সাবট্র্যাকশন অপারেশন সমর্থন করে। UIBezierPath কাস্টম মাস্ক (maskView), ক্লিপিং পাথ এবং জটিল আকার — তারা, হৃদয়, কাস্টম আইকনের জন্য সুবিধাজনক।
Android-এ, একটি কাস্টম ভিউ onDraw(Canvas) ওভাররাইড করে View এক্সটেন্ড করে। Canvas-এ মোবাইল ডেভেলপমেন্টের সব অঙ্কন পদ্ধতি রয়েছে: drawCircle, drawRect, drawLine, drawText, drawBitmap, drawPath এবং drawRoundRect। Paint প্যারামিটার কনফিগার করে — রং, লাইনের পুরুত্ব, শৈলী (FILL, STROKE, FILL_AND_STROKE), অ্যান্টি-আলিয়াসিং (isAntiAlias) এবং টেক্সটের আকার। onDraw প্রতিটি invalidate()-এ কল করা হয় এবং এতে ভারী অপারেশন থাকা উচিত নয় — সব গণনা ক্যাশে করা হয়।
class CustomCircleView(context: Context, attrs: AttributeSet?)
: View(context, attrs) {
private val paint = Paint().apply {
style = Paint.Style.FILL
color = Color.BLUE
isAntiAlias = true
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val cx = width / 2f
val cy = height / 2f
val radius = minOf(cx, cy) - 4f
canvas.drawCircle(cx, cy, radius, paint)
}
}
Android-এ Path, UIBezierPath-এর সমতুল্য: addCircle, addRect, addOval, lineTo, cubicTo এবং quadTo। PathMeasure পাথের দৈর্ঘ্য এবং যেকোনো বিন্দুতে স্থানাঙ্ক গণনা করে — পাথ বরাবর অবজেক্টের গতি অ্যানিমেট করার জন্য দরকারী। অ্যানিমেশনের জন্য, কলব্যাকে invalidate() সহ ValueAnimator ব্যবহার করা হয়। অ্যানিমেটর রং, ব্যাসার্ধ, অবস্থান পরিবর্তন করতে পারে — অঙ্কনকে প্রভাবিত করে এমন যেকোনো সম্পত্তি। Android-এ কাস্টম ভিউ XML-এর মাধ্যমে অ্যানিমেশনের জন্য StateListDrawable এবং animated-vector-ও সমর্থন করে।
Android-এ গ্রেডিয়েন্ট Shader-এর মাধ্যমে সেট করা হয় — LinearGradient, RadialGradient এবং SweepGradient। Shader paint.setShader(shader)-এর মাধ্যমে Paint-এ অ্যাসাইন করা হয়। LinearGradient দুটি বিন্দুর মধ্যে ঐচ্ছিক রং অবস্থানের সাথে একটি লিনিয়ার গ্রেডিয়েন্ট জেনারেট করে। RadialGradient — কেন্দ্র থেকে প্রান্ত পর্যন্ত রেডিয়াল। SweepGradient — একটি কেন্দ্র বিন্দুর চারপাশে শঙ্কু আকৃতির। Shader.TileMode (CLAMP, REPEAT, MIRROR) এলাকার সীমানার বাইরে আচরণ নির্ধারণ করে।
Flutter CustomPainter ব্যবহার করে — paint(Canvas canvas, Size size) এবং shouldRepaint পদ্ধতি সহ একটি ক্লাস। Flutter-এ Canvas একই পদ্ধতি প্রদান করে যা Android-এ আছে: drawCircle, drawRect, drawLine, drawPath, drawParagraph এবং drawImage। Flutter-এ Paint রং, পুরুত্ব, শৈলী এবং অ্যান্টি-আলিয়াসিং কনফিগার করে। Flutter drawRect বা onDraw ব্যবহার করে না — সব অঙ্কন CustomPainter-এর মাধ্যমে হয়, যা CustomPaint উইজেটে এম্বেড করা থাকে।
class CirclePainter extends CustomPainter {
final Color color;
CirclePainter({required this.color});
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = color
..style = PaintingStyle.fill
..isAntiAlias = true;
final radius = size.shortestSide / 2 - 4;
canvas.drawCircle(size.center(Offset.zero), radius, paint);
}
@override
bool shouldRepaint(CirclePainter oldDelegate) =>
oldDelegate.color != color;
}
shouldRepaint নির্ধারণ করে যে CustomPainter-কে পুনরায় আঁকতে হবে কিনা। শুধুমাত্র তখন true রিটার্ন করুন যখন রেন্ডারিংকে প্রভাবিত করে এমন ডেটা পরিবর্তন হয় — রং, আকার, চার্ট ডেটা। RepaintBoundary পুনঃঅঙ্কনকে একটি আলাদা লেয়ারে আলাদা করে — উইজেটের জন্য ব্যবহার করুন যা খুব কমই পরিবর্তিত হয়। Flutter-এ setNeedsDisplay বা invalidate নেই — setState বা ValueNotifier-এর মাধ্যমে পরিবর্তন শুনে পুনঃঅঙ্কন ট্রিগার করা হয়।
Flutter LinearGradient, RadialGradient এবং SweepGradient সমর্থন করে — Android-এর মতো একই ধরনের। Gradient createShader(Rect bounds)-এর মাধ্যমে Paint-এর জন্য Shader তৈরি করে। ট্রান্সফর্মেশন canvas.rotate, canvas.scale, canvas.translate এবং canvas.skew-এর মাধ্যমে করা হয়। Flutter Transform উইজেটের জন্য 4x4 ট্রান্সফর্মেশন ম্যাট্রিক্স (Matrix4) ব্যবহার করে। Flutter-এ অঙ্কন অ্যানিমেশন CustomPainter পুনরায় আঁকার জন্য setState-এর সাথে AnimationController-এর মাধ্যমে তৈরি করা হয়।
কাস্টম ভিউ-এর সঠিক মাপন অনুমানযোগ্য ইন্টারফেস আচরণের ভিত্তি। iOS-এ, ভিউ-এর আকার sizeThatFits এবং intrinsicContentSize-এর মাধ্যমে নির্ধারিত হয়। sizeThatFits প্রদত্ত সীমাবদ্ধতার জন্য সর্বোত্তম আকার রিটার্ন করে। intrinsicContentSize — বাহ্যিক সীমাবদ্ধতা ছাড়া বিষয়বস্তুর প্রাকৃতিক আকার। Android-এ, মাপন MeasureSpec প্যারামিটার (UNSPECIFIED, EXACTLY, AT_MOST) সহ onMeasure-এ বাস্তবায়িত হয়। Flutter-এ, আকার paint(Canvas, Size)-এ পাস করা হয় এবং computeDryLayout বা LayoutBuilder-এর মাধ্যমে গণনা করা যেতে পারে।
intrinsicContentSize CGSize রিটার্ন করে — এর বিষয়বস্তুর উপর ভিত্তি করে ভিউ-এর প্রাকৃতিক আকার। setContentHuggingPriority এবং setContentCompressionResistancePriority প্রসারণ এবং সংকোচনের সময় আচরণ নিয়ন্ত্রণ করে। sizeThatFits Auto Layout-এ আকার গণনার জন্য সিস্টেম দ্বারা কল করা হয়। কাস্টম ভিউ-এর জন্য, intrinsicContentSize ওভাররাইড করুন যদি আপনার কম্পোনেন্টের একটি প্রাকৃতিক আকার থাকে — উদাহরণস্বরূপ, একটি বৃত্ত সবসময় 100x100 হওয়া উচিত।
onMeasure widthMeasureSpec এবং heightMeasureSpec গ্রহণ করে। MeasureSpec-এ মোড এবং আকার থাকে: UNSPECIFIED (সীমাবদ্ধতা ছাড়া, ভিউ নিজের আকার বেছে নেয়), EXACTLY (পিতামাতার থেকে সঠিক আকার), AT_MOST (সর্বোচ্চ আকার)। setMeasuredDimension(width, height) মাপনের ফলাফল সংরক্ষণ করে। ডেটা পরিবর্তন হলে, পুনঃমাপনের জন্য requestLayout() কল করুন। নেস্টেড ViewGroup-এর চাইল্ড এলিমেন্ট সাজানোর জন্য onLayout ওভাররাইড করতে হয়।
| প্ল্যাটফর্ম | মাপন পদ্ধতি | পরিবর্তনে কল | রিটার্ন |
|---|---|---|---|
| iOS | sizeThatFits / intrinsicContentSize | setNeedsLayout / invalidateIntrinsicContentSize | CGSize |
| Android | onMeasure / setMeasuredDimension | requestLayout / invalidate | void (আকার সংরক্ষণ করে) |
| Flutter | computeDryLayout | setState / LayoutBuilder | Size |
computeDryLayout পূর্ণ লেআউট চক্র ছাড়া আকার গণনার জন্য RenderObject পদ্ধতি। LayoutBuilder.getSize — build পদ্ধতিতে উপলব্ধ স্থান পাওয়ার একটি বিকল্প। Flutter-এ, ক্যানভাসের আকার paint-এ Size হিসাবে পাস করা হয় এবং আলাদা মাপনের প্রয়োজন হয় না — CustomPainter পাস করা সীমানার মধ্যে আঁকে। তবে, কাস্টম RenderObject-এর জন্য, performLayout এবং computeDryLayout ওভাররাইড করতে হবে।
সচরাচর জিজ্ঞাসিত প্রশ্ন
drawRect Core Graphics-এর মাধ্যমে কাস্টম অঙ্কনের জন্য একটি UIView পদ্ধতি। এটি ভিউ-এর প্রথম রেন্ডারে এবং প্রতিটি setNeedsDisplay() কলের পরে কল করা হয়। লাইন, আকার এবং টেক্সটের জন্য drawRect-এর ভিতরে CGContext ব্যবহার করুন।
View এক্সটেন্ড করে একটি ক্লাস তৈরি করুন, onDraw(Canvas canvas) ওভাররাইড করুন এবং Canvas API ব্যবহার করুন: drawCircle, drawRect, drawPath। Paint রং, পুরুত্ব এবং শৈলী কনফিগার করে। আপডেটের জন্য invalidate() কল করুন।
CustomPainter Canvas-এ কাস্টম অঙ্কনের জন্য একটি Flutter ক্লাস। paint(Canvas, Size) এবং shouldRepaint পদ্ধতি ইমপ্লিমেন্ট করুন। এটি CustomPaint উইজেটের মাধ্যমে স্থাপন করা হয়। Flutter-এ drawRect নেই — সব অঙ্কন CustomPainter-এর মাধ্যমে হয়।
iOS-এ sizeThatFits এবং intrinsicContentSize ব্যবহার করুন। Android-এ — MeasureSpec সহ onMeasure। Flutter-এ, আকার paint(Canvas, Size)-এ পাস করা হয় বা computeDryLayout-এর মাধ্যমে গণনা করা হয়। প্রতিটি প্ল্যাটফর্ম নিজস্ব মাপন পদ্ধতি ব্যবহার করে।
কাস্টম ভিউ অনন্য গ্রাফিক্স, অ্যানিমেশন, চার্ট এবং এমন এলিমেন্টের জন্য প্রয়োজন যা স্ট্যান্ডার্ড UIKit বা View দিয়ে বাস্তবায়ন করা যায় না। সহজ স্টাইলের জন্য, স্ট্যান্ডার্ড কম্পোনেন্ট কনফিগার করাই যথেষ্ট — প্রয়োজন ছাড়া আর্কিটেকচার জটিল করবেন না।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।