brunch

You can make anything
by writing

C.S.Lewis

by myner Jan 10. 2019

[Flutter] 06. 렌더링 원리 part 3.

플러터의 렌더링 원리

(본 글은 공부하며 적은 글로서 100% 맞음을 보장할 수 없습니다. 틀린 곳은 조언해주시면 감사하겠습니다!)


Dart Developers Korea  오픈채팅방 https://open.kakao.com/o/gYyufB6 


지난 글에(https://brunch.co.kr/@myner/7) 이어서 Flutter 렌더링 원리를 이어 보도록 하자! 


CustomRenderObjectWidget 이라고 RenderObjectWidget을 커스텀하여 하나 만들어보자 


이 위젯은 부모로부터 받는 제약 조건이 무엇이든 간에 그 자식에게 최소한의 제약을 전달하는 것으로 하자. 또한, 제공된 모든 너비와 높이를 차지하고 아이를 오른쪽 하단 모서리에 배치하도록 하자.


void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        body: ConstrainedBox(
          constraints: BoxConstraints(
            maxWidth: double.infinity,
            minWidth: 100.0,
            maxHeight: 500.0,
            minHeight: 100.0
          ),
          child: CustomRenderObjectWidget(
            child: Container(
              color: Colors.red,
            )
          ),
        ),
      ),
    )
  );
}


ConstrainedBox는 자식에게 전달할 제약 조건을 명시적으로 지정할 수 있는 위젯다. 따라서 CustomRenderObjectWidget 위젯은 100.0에서 무한대 사이의 너비와 100.0에서 500.0 사이의 높이로 제공된다.


class CustomRenderObjectWidget extends SingleChildRenderObjectWidget {

  Stingy({Widget child}): super(child: child);

  @override
  RenderObject createRenderObject(BuildContext context) {
    return CustomRenderObjectWidgetStingy();
  }
}


SingleChildRenderObjectWidget을 가진다. SingleChildRenderObjectWidget은 이름에서 알 수 있듯이 단일 자식을 허용하는 RenderObjectWidget입니다.

RenderObject를 생성하고 반환하는 createRenderObject 함수는 CustomRenderObjectWidgetStingy를 호출 한 클래스의 인스턴스를 생성한다.


class CustomRenderObjectWidgetStingy extends RenderShiftedBox {

  CustomRenderObjectWidgetStingy(): super(null);

  @override
  void performLayout() {
    child.layout(BoxConstraints(
      minHeight: 0.0,
      maxHeight: constraints.minHeight,
      minWidth: 0.0,
      maxWidth: constraints.minWidth
    ), parentUsesSize: true);


    final BoxParentData childParentData = child.parentData;
    childParentData.offset 
      = Offset(this.constraints.maxWidth - child.size.width,
        this.constraints.maxHeight - child.size.height);

    size = Size(this.constraints.maxWidth, constraints.maxHeight);
  }
}


CustomRenderObjectWidgetStingy는 Box Protocol을보다 쉽게 구현할 수 있도록 RenderBox를 확장하는 많은 도우미 클래스 중 하나 인 RenderShiftedBox를 슈퍼클래스로 한다. RenderShiftedBox는 프로토콜의 모든 세부 사항을 구현하고 performLayout 함수의 구현을 남겨 둡니다. 이 함수에서는 자식을 레이 아웃하고 표시할 오프셋을 결정해야 한다.


자식을 레이 아웃하기 위해서는 child.layout을 호출하고 원하는 제약 조건을 제공하기만 하면 된다. child.layout에 parentUsesSize라는 또 다른 매개 변수를 제공한다. false로 설정하면 부모가 자식의 어떤 크기로 선택하든 신경 쓰지 않아 레이아웃 프로세스를 최적화하는 데 매우 유용하다. 자식이 크기를 변경하면 부모는 다시 레이아웃 할 필요가 없다! 그러나 우리의 경우 우리는 자식을 왼쪽 하단 모서리에 놓기를 원한다. 즉, 우리는 어떤 크기로 선택되는지에 대해 신경 쓰고, parentUsesSize를 true로 설정하도록 하자.


이제 코드를 실행하면 StingyWidget이 부모에 의해 허용된 모든 높이와 너비를 소비 한 다음 크기가 100x100 인 빨간색 직사각형을 오른쪽 하단에 배치한 것을 볼 수 있다.



다음은 앱이 실행될 경우 코드를 따라가며 어떻게 레이아웃 -> 페인트 -> 레스터 라이즈까지 되는지 살펴보도록 하자 


<참고문헌>

https://flutter.io/docs/resources/technical-overview

https://github.com/flutter/flutter  
https://github.com/flutter/engine

https://docs.flutter.io/index.html 

https://zhuanlan.zhihu.com/p/36861174 
https://tech.meituan.com/waimai_flutter_practice.html 
https://www.yuque.com/xytech/flutter/hc0xq7 
https://www.yuque.com/xytech/flutter/tge705 
https://www.jianshu.com/p/e6cd8584fdbb?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation 
https://flutter.io/docs/development/platform-integration/platform-channels


작가의 이전글 [Flutter] 05. 렌더링 원리 part 2.
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari