Flutter CustomPainter를 사용한 커스텀 드로잉
Flutter는 기본 위젯 외에도 복잡하고 정교한 그래픽을 구현할 수 있는 강력한 기능을 제공합니다. 그중 하나가 바로 CustomPainter입니다. CustomPainter를 사용하면 캔버스에 직접 드로잉을 수행할 수 있으며, 복잡한 사용자 정의 UI를 구현할 때 유용합니다.
이번 글에서는 CustomPainter의 기본 개념부터 실습 예제까지 다루며, 사용법과 최적화 팁을 안내합니다.
📌 1. CustomPainter란?
CustomPainter는 Flutter에서 저수준 그래픽을 그릴 수 있는 클래스로, 캔버스(Canvas)를 활용해 자유로운 형태의 UI를 만들 수 있습니다. Flutter에서 제공하는 기본 위젯으로 구현하기 어려운 도형, 차트, 애니메이션 등을 구현할 수 있습니다.
✅ 주요 특징
- 저수준 드로잉: 사각형, 원, 곡선, 텍스트 등 다양한 형태를 직접 그릴 수 있음
- 고성능: Flutter의 저수준 렌더링 엔진을 활용해 성능 최적화 가능
- 재사용성: 여러 위젯에서 동일한 CustomPainter를 재활용 가능
✅ CustomPainter의 주요 메서드
메서드 | 설명 |
paint(Canvas, Size) | 캔버스에 그림을 그리는 메서드 |
shouldRepaint() | 다시 그릴 필요가 있는지 여부를 반환함 |
📌 2. 기본적인 CustomPainter 구현
✅ CustomPainter 기본 구조
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: CustomPainterExample(),
);
}
}
class CustomPainterExample extends StatelessWidget {
const CustomPainterExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('CustomPainter 예제')),
body: Center(
child: CustomPaint(
size: const Size(200, 200),
painter: CirclePainter(),
),
),
);
}
}
class CirclePainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.blue
..style = PaintingStyle.fill;
canvas.drawCircle(Offset(size.width / 2, size.height / 2), 80, paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
✅ 코드 설명
- CustomPaint 위젯을 사용해 CirclePainter를 등록
- Canvas.drawCircle()로 원 그리기
- shouldRepaint()에서 재렌더링 여부 결정
📌 3. 다양한 도형 그리기
✅ 1) 사각형(Rectangle) 그리기
canvas.drawRect(Rect.fromLTWH(50, 50, 100, 100), paint);
✅ 2) 선(Line) 그리기
canvas.drawLine(Offset(0, 0), Offset(100, 100), paint);
✅ 3) 경로(Path) 그리기
final path = Path()
..moveTo(50, 50)
..lineTo(150, 50)
..lineTo(100, 150)
..close();
canvas.drawPath(path, paint);
📌 4. CustomPainter 활용 예제
✅ 1) 사용자 입력을 기반으로 드로잉
아래 예제는 화면에서 사용자가 터치한 지점을 따라 선을 그리는 예제입니다.
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: DrawingExample(),
);
}
}
class DrawingExample extends StatefulWidget {
const DrawingExample({super.key});
@override
State<DrawingExample> createState() => _DrawingExampleState();
}
class _DrawingExampleState extends State<DrawingExample> {
final List<Offset> _points = [];
@override
Widget build(BuildContext context) {
return GestureDetector(
onPanUpdate: (details) {
setState(() {
_points.add(details.localPosition);
});
},
onPanEnd: (_) => _points.clear(),
child: CustomPaint(
size: Size.infinite,
painter: LinePainter(_points),
),
);
}
}
class LinePainter extends CustomPainter {
final List<Offset> points;
LinePainter(this.points);
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.red
..strokeWidth = 4.0
..strokeCap = StrokeCap.round;
for (int i = 0; i < points.length - 1; i++) {
canvas.drawLine(points[i], points[i + 1], paint);
}
}
@override
bool shouldRepaint(LinePainter oldDelegate) => true;
}
📌 5. 성능 최적화 팁
- shouldRepaint: 불필요한 재렌더링을 방지
- Layer 분리: 복잡한 드로잉은 PictureRecorder 사용
- Path 캐싱: 동일한 Path는 캐싱하여 성능 최적화
📌 6. 결론
Flutter의 CustomPainter는 정교한 그래픽과 맞춤형 UI를 구현하는 강력한 도구입니다. 간단한 도형부터 복잡한 사용자 입력 기반 드로잉까지 다양한 방식으로 활용할 수 있습니다.
- 간단한 도형: drawCircle(), drawRect()
- 사용자 입력: GestureDetector와 결합해 동적 드로잉
프로젝트에서 창의적인 UI를 구현하고 싶다면 CustomPainter를 적극적으로 활용해 보세요!
'Flutter' 카테고리의 다른 글
Flutter 레이아웃 시스템 비교: Column, Row, Flex, Stack (0) | 2025.01.19 |
---|---|
Flutter의 GestureDetector와 InkWell 비교 (0) | 2025.01.19 |
Flutter 애니메이션: AnimationController vs TweenAnimationBuilder (0) | 2025.01.18 |
Flutter의 Navigator 2.0과 go_router 비교 및 사용법 (0) | 2025.01.18 |
Flutter Hooks와 hooks_riverpod의 활용법 (0) | 2025.01.18 |