0Pricing
Flutter Mobile Development · Урок

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: paint and shouldRepaint.

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 true if the new delegate (the updated painter) has different data that would change the drawing.
  • Return false if 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:

  • CustomPainter is your entry point for custom visuals.
  • The Canvas object is your drawing surface with a top-left origin.
  • The Paint object defines the style (color, stroke, fill).
  • How to draw basic shapes like lines, circles, and rectangles.
  • shouldRepaint helps optimize performance.
  • Path allows 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 включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. CustomPainter и Canvas
  2. Неявные анимации
  3. Явные анимации и Hero
  4. Пошаговые и физические анимации
← Назад к Flutter Mobile Development