CustomPainter وCanvas
تعمّق في الرسم المخصّص باستخدام `CustomPainter` وواجهة API `Canvas` لإنشاء أشكال ومخططات وتأثيرات مرئية فريدة
CustomPainter وCanvas درس مجاني في Flutter Mobile Development على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Flutter Mobile Development، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Flutter Mobile Development 4 دروس في المجموع.
بعض أجزاء هذا الدرس لم تُترجم بعد وتظهر باللغة الإنجليزية.
Intro to Custom Drawing
Flutter's widgets are powerful, but sometimes you need to draw something truly unique. Think custom graphs, unique shapes, or special visual effects!
This is where custom drawing comes in. It gives you pixel-level control over what appears on the screen, letting you create anything imaginable.
Meet CustomPainter
At the heart of custom drawing in Flutter is the CustomPainter class. You extend this class to define what and how to draw.
- It provides a canvas to draw on.
- It requires you to implement two key methods:
paintandshouldRepaint.
The Canvas: Your Drawing Board
The paint method receives a Canvas object. Think of the Canvas as your blank drawing board, ready for your artistic commands.
It uses a 2D Cartesian coordinate system: the top-left corner is (0,0). X-values increase to the right, and Y-values increase downwards.
Styling with Paint
Before you draw, you need to tell Flutter how to draw. This is done using a Paint object. The Paint object defines properties like:
- Color: What color should the drawing be?
- StrokeWidth: How thick should lines be?
- Style: Should it be filled (
PaintingStyle.fill) or just an outline (PaintingStyle.stroke)?
Drawing Basic Shapes: Line
Let's draw our first shape: a simple line! We use canvas.drawLine(), providing start and end points (Offset) and our Paint style.
Try running this example:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Draw Line')),
body: Center(
child: CustomPaint(
painter: LinePainter(),
child: Container(),
),
),
),
);
}
}
class LinePainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.blue
..strokeWidth = 4.0
..style = PaintingStyle.stroke;
final p1 = Offset(0, size.height / 2);
final p2 = Offset(size.width, size.height / 2);
canvas.drawLine(p1, p2, paint);
}
@override
bool shouldRepaint(covariant LinePainter oldDelegate) => false;
}Drawing Basic Shapes: Circle
Drawing a circle is just as easy with canvas.drawCircle(). You need a center point, a radius, and a Paint object.
Notice how we use size.width / 2 and size.height / 2 to center our drawings.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Draw Circle')),
body: Center(
child: CustomPaint(
painter: CirclePainter(),
child: Container(),
),
),
),
);
}
}
class CirclePainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.red
..strokeWidth = 5.0
..style = PaintingStyle.fill;
final center = Offset(size.width / 2, size.height / 2);
final radius = size.width / 4;
canvas.drawCircle(center, radius, paint);
}
@override
bool shouldRepaint(covariant CirclePainter oldDelegate) => false;
}Drawing Basic Shapes: Rectangle
To draw a rectangle, we use canvas.drawRect(). This method takes a Rect object, which defines the rectangle's position and size.
A Rect.fromLTWH constructor is useful for defining a rectangle from its left, top, width, and height.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Draw Rectangle')),
body: Center(
child: CustomPaint(
painter: RectanglePainter(),
child: Container(),
),
),
),
);
}
}
class RectanglePainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.green
..strokeWidth = 3.0
..style = PaintingStyle.stroke;
final rect = Rect.fromLTWH(size.width * 0.2, size.height * 0.2, size.width * 0.6, size.height * 0.6);
canvas.drawRect(rect, paint);
}
@override
bool shouldRepaint(covariant RectanglePainter oldDelegate) => false;
}The shouldRepaint Method
The shouldRepaint method in CustomPainter is crucial for performance. It tells Flutter whether your custom painting needs to be redrawn.
- Return
trueif the new delegate (the updated painter) has different data that would change the drawing. - Return
falseif the drawing would be identical. This prevents unnecessary repaints and saves CPU cycles.
For static drawings, false is often sufficient.
Drawing Complex Shapes with Path
For more complex or irregular shapes, you'll use a Path object. A Path allows you to define a series of connected lines and curves.
You can move to a point (moveTo), draw lines to points (lineTo), and finally close the path (close) before drawing it with canvas.drawPath().
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Draw Triangle')),
body: Center(
child: CustomPaint(
painter: TrianglePainter(),
child: Container(),
),
),
),
);
}
}
class TrianglePainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.purple
..style = PaintingStyle.fill;
final path = Path();
path.moveTo(size.width / 2, size.height * 0.1);
path.lineTo(size.width * 0.9, size.height * 0.9);
path.lineTo(size.width * 0.1, size.height * 0.9);
path.close();
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(covariant TrianglePainter oldDelegate) => false;
}Test Your Knowledge!
Which of the following statements about Flutter's custom drawing is TRUE?
Recap: Custom Drawing Basics
You've taken your first steps into custom drawing in Flutter! You learned:
CustomPainteris your entry point for custom visuals.- The
Canvasobject is your drawing surface with a top-left origin. - The
Paintobject defines the style (color, stroke, fill). - How to draw basic shapes like lines, circles, and rectangles.
shouldRepainthelps optimize performance.Pathallows for drawing complex, custom shapes.
Keep experimenting to bring your unique designs to life!
الأسئلة الشائعة
هل درس «CustomPainter وCanvas» مجاني؟
نعم — نص درس «CustomPainter وCanvas» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Flutter Mobile Development، انتقل إلى CoddyKit PRO. تتضمن دورة Flutter Mobile Development 4 دروس في المجموع.
ماذا ستتعلم في «CustomPainter وCanvas»؟
تعمّق في الرسم المخصّص باستخدام `CustomPainter` وواجهة API `Canvas` لإنشاء أشكال ومخططات وتأثيرات مرئية فريدة تتمرن على Flutter Mobile Development مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Flutter Mobile Development؟
لا تُشترط خبرة سابقة. Flutter Mobile Development على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «CustomPainter وCanvas»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Flutter Mobile Development هذا؟
نعم. كل درس في Flutter Mobile Development يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- CustomPainter وCanvas
- الرسوم المتحركة الضمنية
- الرسوم المتحركة الصريحة وHero
- الحركات المتدرجة والقائمة على الفيزياء