[flutter]CustomDropdownButton Example

김영진·2021년 8월 5일
1

Flutter 앱 개발 일기

목록 보기
16/31
post-custom-banner

목적

유튜브 제임쓰님의 최근 영상에 플러터가 제공하는 위젯 없이 랜더 오브젝트를 활용하여 드랍다운을 구현한 예제가 있어 내부적으로 어떻게 돌아가는지 분석해 보았다.

내용

구조

	NavigatorState navigator = Navigator.of(context);
        final RenderBox itemBox = context.findRenderObject()! as RenderBox;
        final Rect itemRect = itemBox.localToGlobal(
        Offset.zero, ancestor: navigator.context.findRenderObject()) & itemBox.size;
  • navigator : 부모 위젯의 컨텍스트 (RenderPointerListener#3ade6)
  • itemBox : 드롭다운 버튼 위젯의 랜드박스 (RenderSemanticsGestureHandler#965c0 relayoutBoundary=up3)
  • itemRect : 드롭다운 버튼의 자식들이 그려질 좌표(Rect.fromLTRB(126.5, 230.5, 326.5, 270.5))
  • localToGlobal(...) : Offset(x,y)
  • itemBox.size : Size(x,y)
  • & 연산하면 Rect.fromLTRB 로 변경됨.. 신기
await navigator.push(
// MaterialPageRouter 대신 사용
          PageRouteBuilder(
            barrierDismissible: true,
            opaque: false,
            pageBuilder: (context, anim1, anim2) => Container(
              child: DefaultTextStyle(
                style: TextStyle(color: Colors.black),
                // Stack 사용
                child: Stack(
                  children: [
                    Positioned(
                    // 부모위젯의 위치에 부모위젯의 크기만큼을 더해 포지셔닝
                      top: itemRect.top+itemBox.size.height,
                      // 아래로 내려갈거니까 부모위젯의 위치만큼 좌측에 띄워 포지셔닝
                      left: itemRect.left,
                      width: itemBox.size.width,
                      child: Container(
                        decoration: BoxDecoration(
                          color: Colors.grey[200],
                          border: Border.all(color: Colors.black)
                        ),
                        child: this.widget.scrollCheck
                          ? Container(
                              height: this.widget.itemHeight,
                              child: ListView(
                                padding: EdgeInsets.zero,
                                children: this.widget.items.map<Widget>(
                                  (String e) => GestureDetector(
                                    onTap: () => this.widget.onTap(e),
                                    child: Container(
                                      alignment: Alignment.center,
                                      decoration: BoxDecoration(
                                        color: Colors.white,
                                        border: Border.all(color: Colors.black)
                                      ),
                                      padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 10.0),
                                      margin: EdgeInsets.all(10.0),
                                      child: Text(e)
                                    ),
                                  )
                                ).toList(),
                              ),
                            )
                          : Column(
                              children: this.widget.items.map<Widget>(
                                (String e) => GestureDetector(
                                  onTap: () => this.widget.onTap(e),
                                  child: Container(
                                    alignment: Alignment.center,
                                    decoration: BoxDecoration(
                                      color: Colors.white,
                                      border: Border.all(color: Colors.black)
                                    ),
                                    padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 10.0),
                                    margin: EdgeInsets.all(10.0),
                                    child: Text(e)
                                  ),
                                )
                              ).toList(),
                            ),
                      ),
                    )
                  ],
profile
2021.05.03) Flutter, BlockChain, Sports, StartUp
post-custom-banner

2개의 댓글

comment-user-thumbnail
2021년 8월 15일

🤩 👍

1개의 답글