본문 바로가기
Flutter

CustomPainter를 redraw 하는 방법

by 붕어사랑 티스토리 2024. 3. 15.
반응형

https://api.flutter.dev/flutter/rendering/CustomPainter-class.html

 

CustomPainter class - rendering library - Dart API

The interface used by CustomPaint (in the widgets library) and RenderCustomPaint (in the rendering library). To implement a custom painter, either subclass or implement this interface to define your custom paint delegate. CustomPainter subclasses must impl

api.flutter.dev

 

공식문서에서는 커스텀 페인터를 redraw하는 방법을 아래와 같이 설명하고 있다

 

 

The most efficient way to trigger a repaint is to either:

 

  • Extend this class and supply a repaint argument to the constructor of the CustomPainter, where that object notifies its listeners when it is time to repaint.
  • Extend Listenable (e.g. via ChangeNotifier) and implement CustomPainter, so that the object itself provides the notifications directly.

 

 

대충 repaint라는 걸 생성자에 전달한 다음에 CustomPainter에다가 다시 넘겨주라는 내용과

리스너블이라는 것을 상속받고 CustomPainter를 구현해라 라는 내용이다.

 

여기서 리스너블이라는것은 ChangeNotifier같은걸 말한다. 우리가 프로바이더에서 보던것들!

 

클래스 하이어라키를 보면 다음과 같다.

 

 

 

 

앞서 언급한 방법의 2번째, 상속받고 커스텀페인터 구현은 너무 어려어 보인다. 어떻게 해야할지도 난감하고. 가장 쉬운 방법인 repaint를 상속하는 방법을 알아보자

 

 

 

 

 

 

 

1. 구조 파악

먼저 커스텀페인터의 코드를 보면 아래와 같이 Listenable을 옵셔널로 받고있다. 그리고 변수명 이름이 무려 repaint이다!!!

 

 

그리고 리스너블은 추상클래스이다. 이것에 대한 구현체들이 ValueListenable이랑 ChangeNotifier등이 있다. 대충 감이 오지 않은가?

 

repaint에다가 ChangeNotifier를 넘겨주고 notifyListener를 호출해주면 CustomPainter가 repaint 된다!

 

 

 

2. 코드 작성

 

먼저 리스너블을 작성해주자. 나는 list 하나 가지고 있고, 이를 add 할 때 마다 CustomPainter를 다시 그리고 싶다!

그러면 아래처럼 add할 때 notifyListeners를 호출해주면 된다

class MyListenableList extends ChangeNotifier {
  final List<double> datas = [];
  
  get length => datas.length;
  get isEmpty => datas.isEmpty;
  
  void add(double value) {
    datas.add(value);
    notifyListeners();
  }
  
  void removeAt(int index){
    datas.removeAt(index);
  }

}

 

 

아래처럼 커스텀 페인터에다가 Listenable들을 받아오고, 이를 super를 통해 CustomPainter에 넘겨준다

class MyCustomPainter extends CustomPainter {

  MyListenableList? data;
  
  MyCustomPainter({this.data}) : super(repaint: data);

  @override
  void paint(Canvas canvas, Size size) {
    //대충 그리는 코드
  }

  @override
  bool shouldRepaint(MyCustomPainter oldDelegate) {
  	return true;
  }
}

 

 

 

테스트해보니 잘 작동함!

 

 

이렇게 중요한게 왜 교육자료에는 없고 공식문서에서도 찾아보기 힘들게 되어있을까?

 

 

반응형

댓글