[Flutter] CustomPainter

2024. 2. 14. 17:38dev/flutter

728x90
반응형

CustomPaint는 그림을 그리는 위젯이다.

마치 Container나 SizedBox를 쓰듯이 말이다.

 

 CustomPaint위젯 안에 그림을 그려주는 것이 Painter이다.

Painter CustomPainter클래스를 재정의하여 사용한다.

 

CustomPaint안에서 그림을 그려지는 순서는 

painter → child → foregroundPainter 순으로 그려진다.

child: Center(
  child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
      CustomPaint(
        painter: BlueBoxPainter(),
        child: Container(
          width: 50,
          height: 50,
          color: Colors.orange.withOpacity(0.8),
        ),
        foregroundPainter: RedLinePainter(),
      ),
    ],
  ),
),

 

 

shouldRepaint는 이어서 색칠하느냐 마느냐로 이해하면 된다.

보통 화면을 새로 그린다는데 그럼 뭔가 새로고침 리셋 되는 느낌이다.

@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
  return false;
}

 

 

 

위젯의 크기는 부모 > 자식>그 외 크기(size)관계이다

부모 크기가 없다면 자식의 크기로 표출된다.

Container(
  width: 200,
  height: 200,
  child: CustomPaint(
    size: Size(100, 100),
    painter: NPainter(),
    child: Container(
      width: 50,
      height: 50,
      decoration: BoxDecoration(
        border: Border.all(
          color: Colors.orange,
          width: 3.0
        ),
      ),
    ),
  ),
),

 

부모有

200x200

 

자식有

100x100

 

CustomPaint Size만 있는 경우

150x150

 

 

원형 파이 차트 참고 코드

링크 : https://iosroid.tistory.com/33

class PercentDonutPainter extends CustomPainter {
  double percentage;
  double textScaleFactor = 1.0;
  Color activeColor;
  PercentDonutPainter({required this.percentage, required this.activeColor});

  @override
  void paint(Canvas canvas, Size size) {
    // background paint
    Paint paint = Paint()
        ..color = const Color(0xfff3f3f3)
        ..strokeWidth = 15.0
        ..style = PaintingStyle.stroke
        ..strokeCap = StrokeCap.round;

    double radius = math.min(size.width / 2 - paint.strokeWidth / 2, size.height / 2 - paint.strokeWidth / 2);
    Offset center = Offset(size.width / 2, size.height / 2);
    canvas.drawCircle(center, radius, paint);

    // active paint
    double arcAngle = math.pi * 2 * percentage;
    paint.color = activeColor;
    canvas.drawArc(Rect.fromCircle(center: center, radius: radius), -math.pi / 2, arcAngle, false, paint);

    // text
    String text = '${(percentage * 100).round()} / 100';

    double fontSize = size.width / text.length * textScaleFactor;
    TextSpan sp = TextSpan(
      style: TextStyle(
        fontSize: fontSize,
        fontWeight: FontWeight.bold,
        color: Colors.black,
      ),
      text: text,
    );

    TextPainter tp = TextPainter(text: sp, textDirection: TextDirection.ltr);
    tp.layout();    // 텍스트의 크기와 방향을 정함
    double dx = size.width / 2 - tp.width / 2;
    double dy = size.height / 2 - tp.height / 2;

    Offset offset = Offset(dx, dy);
    tp.paint(canvas, offset);
  }

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

 

 

 

사각(Rectangle) 페인트

속은 꽉차게하려면 Paint에 PaintingStyle을 fill을 주면 됨

class LuxGaugePainter extends CustomPainter {
  LuxGaugePainter({required this.gauge}){
   debugPrint('[LuxGaugePainter].. gauge:$gauge');
  }

  final double gauge;

  @override
  void paint(Canvas canvas, Size size) {
    canvas.drawRect(
      Rect.fromLTWH(0, 0, gauge.toDouble(), size.height),
      _GaugePaint()
    );
  }

  @override
  bool shouldRepaint(covariant LuxGaugePainter oldDelegate) => oldDelegate.gauge != gauge;
}

// green painter
class _GaugePaint extends Paint{
  _GaugePaint() {
    color = Colors.green;
    strokeCap = StrokeCap.square;
    style = PaintingStyle.fill;
  }
}

 

살짝 Radius주기

final Radius rectRadius = const Radius.circular(16.0);

canvas.drawRRect(
  RRect.fromRectAndCorners(
    Rect.fromLTWH(0, 0, gauge.toDouble(), size.height),
    topLeft: rectRadius,
    topRight: rectRadius,
    bottomRight: rectRadius,
    bottomLeft: rectRadius
  ),
  _GaugePaint()
);
}

728x90
반응형

'dev > flutter' 카테고리의 다른 글

[Flutter] TextField  (0) 2024.02.21
[Flutter] Geolocator #location  (0) 2024.02.21
[Flutter] landscape, portrait #fullscreen #system  (0) 2024.02.11
[Flutter] Lifecycle  (1) 2024.02.07
[Flutter] FutureBuilder  (0) 2024.02.02