مقدمة إلى CustomPainter
مقدمة إلى CustomPainter
تغطي ودجات Flutter المدمجة نطاقاً واسعاً من أنماط واجهة المستخدم، لكن في بعض الأحيان تحتاج إلى رسم شيء لا يوفره أي ودجت — مخطط مخصص، أو مؤشر تقدم فريد، أو شكل زخرفي، أو كائن لعبة. لهذه الحالات، تكشف Flutter عن واجهة برمجية منخفضة المستوى للرسم على Canvas من خلال الفئة CustomPainter. عبر اشتقاق فئة من CustomPainter وإرفاقها بودجت CustomPaint، تحصل على وصول مباشر إلى سطح العرض ويمكنك رسم أي شيء يمكن وصفه رياضياً.
عقد CustomPainter
يجب على كل رسّام مخصص تنفيذ طريقتين فقط:
paint(Canvas canvas, Size size)— تستدعيها الإطار في كل مرة يحتاج فيها الودجت إلى الرسم. تصدر أوامر الرسم على كائنCanvas؛ وتخبركSizeبحجم المساحة المتاحة.shouldRepaint(CustomPainter oldDelegate)— تُستدعى قبل كل إعادة رسم محتملة. أعدtrueإذا كانت بيانات الرسّام الجديد مختلفة عن القديم وكانت إعادة الرسم ضرورية؛ أعدfalseلتخطي إعادة الرسم المكلفة.
shouldRepaint هي ضمانة للأداء. إعادة true دون شرط آمنة لكنها مهدِرة — كل إعادة بناء للأب ستطلق إعادة رسم كاملة للـ Canvas. قارن دائماً الحقول ذات الصلة وأعد false عندما لا يتغير شيء.أول CustomPainter لك
أبسط رسّام ممكن يشتق من CustomPainter، ويتجاوز الطريقتين المطلوبتين، ويرسم دائرة مملوءة في مركز الـ Canvas.
CustomPainter بسيط للغاية
import 'package:flutter/material.dart';
class CirclePainter extends CustomPainter {
final Color color;
final double radius;
const CirclePainter({required this.color, required this.radius});
@override
void paint(Canvas canvas, Size size) {
// تحديد كيفية ملء الشكل
final paint = Paint()
..color = color
..style = PaintingStyle.fill;
// رسم دائرة في مركز المساحة المتاحة
final centre = Offset(size.width / 2, size.height / 2);
canvas.drawCircle(centre, radius, paint);
}
@override
bool shouldRepaint(CirclePainter oldDelegate) {
// إعادة الرسم فقط إذا تغير المظهر فعلياً
return oldDelegate.color != color || oldDelegate.radius != radius;
}
}
إرفاق الرسّام بواسطة CustomPaint
لا يُوضع نسخة CustomPainter مباشرةً في شجرة الودجات. بل تلفها في ودجت CustomPaint، الذي يخصص Canvas للرسّام ويدير دورة حياته.
استخدام CustomPaint في شجرة الودجات
class PainterDemo extends StatelessWidget {
const PainterDemo({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Custom Painter Demo')),
body: Center(
child: CustomPaint(
// تحديد حجم صريح للـ Canvas
size: const Size(300, 300),
painter: CirclePainter(
color: Colors.deepPurple,
radius: 100,
),
// ودجات الأبناء تُعرض فوق المحتوى المرسوم
child: const Center(
child: Text(
'Hello Canvas!',
style: TextStyle(color: Colors.white, fontSize: 18),
),
),
),
),
);
}
}
CustomPaint كلاً من painter (يُرسم خلف الابن) وforegroundPainter (يُرسم أمام الابن). استخدم foregroundPainter عندما تريد أن يتراكب المحتوى المرسوم فوق ودجت الابن، مثل شارة أو حلقة تمييز.كائن Paint — فرشاة الرسم
قبل إصدار أي أمر رسم على الـ Canvas، تهيئ كائن Paint الذي يعمل كفرشاة قابلة للضبط. أكثر الخصائص استخداماً هي:
color— لون التعبئة أو الحدود.style—PaintingStyle.fillيملأ الشكل؛PaintingStyle.strokeيرسم الحدود فقط.strokeWidth— سماكة الحدود، بالبكسل المنطقي.isAntiAlias— تنعيم حواف المنحنيات (الافتراضيtrue).shader— تطبيق تدرجات أو أنماط صور بدلاً من لون ثابت.
أوامر الرسم الأساسية في Canvas
تكشف الفئة Canvas عن واجهة برمجية غنية. أكثر الطرق أهمية للمبتدئين هي:
canvas.drawCircle(Offset centre, double radius, Paint paint)canvas.drawRect(Rect rect, Paint paint)canvas.drawLine(Offset p1, Offset p2, Paint paint)canvas.drawPath(Path path, Paint paint)— للأشكال التعسفية.canvas.drawOval(Rect rect, Paint paint)canvas.drawRRect(RRect rrect, Paint paint)— مستطيلات بزوايا مستديرة.
CustomPaint، مع زيادة x نحو اليمين وزيادة y نحو الأسفل. إذا ظهر رسمك مقصوصاً أو خارج الشاشة، تحقق من أنك تستخدم الأصل الصحيح وأن شكلك يناسب Size المتاحة.إطلاق إعادة الرسم مع AnimationController أو setState
الرسّام الثابت مفيد، لكن القوة الحقيقية تظهر عند دمج CustomPainter مع AnimationController أو مع StatefulWidget يمرر بيانات جديدة إلى مُنشئ الرسّام. في كل مرة يستدعي فيها الأب setState بقيمة جديدة، تتحقق Flutter من shouldRepaint، وإذا أعادت true، تستدعي paint مرة أخرى بالبيانات المحدّثة — مما ينتج رسومات ناعمة وتفاعلية.
ملخص
لرسم رسومات مخصصة في Flutter، تشتق فئة من CustomPainter، وتنفذ paint() لإصدار أوامر Canvas، وتنفذ shouldRepaint() للتحكم في توقيت إعادة الرسم. يُرفق الرسّام بشجرة الودجات عبر ودجت CustomPaint، الذي يوفر Canvas بحجم صحيح. يعمل كائن Paint كفرشاتك القابلة للضبط، وتكشف واجهة Canvas البرمجية عن مجموعة غنية من أوليات الرسم. يُشكّل هذا الأساس كل شيء بدءاً من الزخارف البسيطة وصولاً إلى الرسومات التفاعلية المخصصة بالكامل في Flutter.