Flutter CustomPaint


CustomPaint는 Flutter에서 사용자 정의 그래픽을 그릴 수 있는 강력한 위젯입니다. CustomPaint는 다양한 형태와 복잡한 그래픽을 그릴 수 있는 기능을 제공하며, 이를 통해 Flutter의 기본 위젯으로는 구현하기 어려운 복잡한 UI를 만들 수 있습니다.

1. CustomPaint의 개요

CustomPaintCustomPainter를 사용하여 사용자 정의 그래픽을 그릴 수 있는 위젯입니다. 이 위젯은 paint 메서드를 통해 자신의 그래픽을 그리는 방식으로 작동하며, 이를 통해 Flutter에서 다양한 형태의 그래픽을 효율적으로 처리할 수 있습니다.

2. 주요 구성 요소

2.1. CustomPaint 위젯

  • painter: CustomPainter를 설정하여 그래픽을 그리는 데 사용됩니다.
  • child: CustomPaint 위젯의 자식 위젯으로, 그래픽이 그려지는 영역 위에 배치됩니다.
CustomPaint(
  painter: MyCustomPainter(),
  child: Container(
    width: 200,
    height: 200,
    child: Center(child: Text('Custom Paint')),
  ),
)

2.2. CustomPainter 클래스

CustomPainterpaint 메서드와 shouldRepaint 메서드를 구현하여 사용자의 그래픽을 그립니다.

  • paint(Canvas canvas, Size size): 실제로 그래픽을 그리는 메서드입니다. Canvas 객체를 사용하여 다양한 그래픽을 그릴 수 있습니다.
  • shouldRepaint(CustomPainter oldDelegate): 이 메서드는 이전 CustomPainter와 현재 CustomPainter가 같으면 false를 반환하고, 다르면 true를 반환하여 애니메이션 등의 업데이트가 필요할 때를 결정합니다.
class MyCustomPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.blue
      ..style = PaintingStyle.stroke
      ..strokeWidth = 5;

    // Draw a rectangle
    canvas.drawRect(Rect.fromLTWH(20, 20, 100, 100), paint);

    // Draw a circle
    paint.color = Colors.red;
    canvas.drawCircle(Offset(150, 150), 50, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}

3. 사용 예제

3.1. 기본 사용법

아래는 간단한 CustomPainter를 사용하여 직사각형과 원을 그리는 예제입니다.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('CustomPaint Example')),
        body: Center(
          child: CustomPaint(
            size: Size(200, 200),
            painter: MyCustomPainter(),
          ),
        ),
      ),
    );
  }
}

class MyCustomPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.blue
      ..style = PaintingStyle.stroke
      ..strokeWidth = 5;

    // Draw a rectangle
    canvas.drawRect(Rect.fromLTWH(20, 20, 100, 100), paint);

    // Draw a circle
    paint.color = Colors.red;
    canvas.drawCircle(Offset(150, 150), 50, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}

3.2. 애니메이션과 함께 사용

CustomPainter는 애니메이션과 결합하여 복잡한 애니메이션 효과를 구현할 수 있습니다. AnimationController와 함께 사용할 때, shouldRepainttrue로 설정하여 애니메이션이 계속해서 업데이트되도록 할 수 있습니다.

예제 코드:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: AnimatedCustomPaint(),
    );
  }
}

class AnimatedCustomPaint extends StatefulWidget {
  @override
  _AnimatedCustomPaintState createState() => _AnimatedCustomPaintState();
}

class _AnimatedCustomPaintState extends State<AnimatedCustomPaint> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    )..repeat(reverse: true);

    _animation = Tween<double>(begin: 50, end: 150).animate(_controller);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Animated CustomPaint')),
      body: Center(
        child: CustomPaint(
          size: Size(200, 200),
          painter: AnimatedPainter(_animation.value),
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

class AnimatedPainter extends CustomPainter {
  final double radius;

  AnimatedPainter(this.radius);

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.blue
      ..style = PaintingStyle.fill;

    // Draw a circle with animated radius
    canvas.drawCircle(size.center(Offset.zero), radius, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}

4. 고급 사용법

4.1. Path 객체 사용

Canvas 클래스의 drawPath 메서드를 사용하여 복잡한 형태를 그릴 수 있습니다. Path 객체를 사용하여 다양한 형태를 정의할 수 있습니다.

예제 코드:

class PathPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.green
      ..style = PaintingStyle.stroke
      ..strokeWidth = 3;

    final path = Path()
      ..moveTo(20, 20)
      ..lineTo(100, 20)
      ..lineTo(100, 100)
      ..close();

    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}

4.2. 클리핑 및 변형

CustomPainter는 클리핑 및 변형 기능을 제공하여 복잡한 그래픽 작업을 수행할 수 있습니다.

예제 코드:

class ClipAndTransformPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.orange
      ..style = PaintingStyle.fill;

    final rect = Rect.fromLTWH(20, 20, 150, 150);
    canvas.save(); // Save the current state
    canvas.clipRect(rect); // Clip the canvas to the rectangle

    // Apply a rotation transformation
    canvas.rotate(0.1);

    // Draw a rectangle
    canvas.drawRect(rect, paint);
    canvas.restore(); // Restore the saved state
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}

5. 요약

  • CustomPaint: 사용자 정의 그래픽을 그릴 수 있는 위젯입니다.
  • CustomPainter: 실제로 그래픽을 그리는 데 사용됩니다. paint 메서드를 구현하여 그래픽을 그리며, shouldRepaint 메서드를 통해 애니메이션이나 상태 변화에 따라 다시 그려야 할지 결정합니다.
  • CanvasPaint: Canvas는 그래픽을 그리는 기본 도구이며, Paint는 선, 색상, 스타일 등을 정의합니다.
  • 애니메이션 및 고급 그래픽: CustomPaint와 애니메이션을 결합하여 동적인 UI를 만들 수 있으며, 복잡한 형태와 변형을 통해 정교한 그래픽을 구현할 수 있습니다.

CustomPaintCustomPainter를 활용하면 Flutter에서 복잡한 그래픽과 애니메이션을 효율적으로 처리할 수 있습니다.


Leave a Reply

Your email address will not be published. Required fields are marked *