구현한 드랍다운 메뉴
Flutter에서 드롭다운 메뉴의 구현 원리
Flutter에서 드롭다운 메뉴는 사용자가 선택 가능한 목록을 제공하는 UI 요소다. DropdownButton, DropdownButtonFormField, 그리고 dropdown_button2 패키지를 활용하면 기본적인 드롭다운을 쉽게 구현할 수 있다.
하지만 서드파티를 쓰기에 앞서 구글이 구현한 드랍다운 버튼이 내부적으로 어떻게 동작하는지, dropdown_button2 패키지를 통해 어떤 최적화 포인트를 찾을 수 있는지 알아보자~ 😆
1. 기본적인 위젯 계층
Flutter의 DropdownButton은 기본적으로 다음과 같은 계층 구조를 가진다.
DropdownButton
├─ StatefulWidget (_DropdownButtonState)
│ ├─ GestureDetector (터치 이벤트 감지)
│ └─ InkWell (시각적 터치 효과)
└─ _DropdownRoute (내부 Route)
└─ OverlayEntry
└─ _DropdownMenu (Material 기반 드롭다운 메뉴)
└─ ListView (메뉴 아이템 리스트 관리)
- 사용자가 버튼을 탭하면 GestureDetector가 이벤트를 감지한다.
- OverlayEntry가 Overlay 위젯에 메뉴를 표시한다.
- 메뉴 아이템이 ListView를 통해 스크롤 가능한 형태로 렌더링된다.
- 선택된 값이 State에 반영되어 UI를 갱신한다.
2. Overlay의 역할
드롭다운 메뉴는 기본적으로 Overlay 위젯을 활용하여 현재 UI 위에 렌더링된다. Overlay는 Flutter의 독립적인 레이어 시스템으로, 기존 위젯 트리와는 별개로 화면의 특정 위치에 위젯을 띄울 수 있게 한다.
final overlayEntry = OverlayEntry(
builder: (context) => Positioned(
top: buttonPosition.dy,
left: buttonPosition.dx,
child: Material(
elevation: 8,
child: ListView(
shrinkWrap: true,
children: items.map((item) => ListTile(
title: Text(item),
onTap: () {
selectedValue = item;
overlayEntry.remove();
},
)).toList(),
),
),
);
Overlay.of(context).insert(overlayEntry);
이렇게 Overlay를 사용하면 기존 UI를 재구성하지 않고도 드롭다운을 자연스럽게 표시할 수 있다.
3. 리스트 빌딩 최적화
드롭다운 메뉴가 많은 항목을 포함할 경우, maxHeight를 활용하여 불필요한 위젯 생성 비용을 줄일 수 있다.
DropdownButton2(
items: List.generate(1000, (index) => DropdownMenuItem(
value: index,
child: Text('Item $index'),
)),
dropdownStyleData: DropdownStyleData(maxHeight: 300),
onChanged: (value) {},
);
위 코드는 1000개의 항목을 생성하지만, DropdownButton 내부에서 모든 위젯이 한 번에 메모리에 로드된다.
DropdownButton2(
items: List.generate(1000, (index) {
return DropdownMenuItem(
value: index,
child: Text('Item $index'),
);
}),
dropdownStyleData: DropdownStyleData(
maxHeight: 300, // 일정 높이 제한 후 스크롤 가능
),
onChanged: (value) {},
);
maxHeight 속성을 사용하여 드롭다운 메뉴의 높이를 제한하여 사용자에게 보이는 항목만 로드할 수 있다. 이렇게 높이가 제한되면 내부적으로 화면에 표시되는 아이템만 렌더링할 수 있다.
'Flutter' 카테고리의 다른 글
Riverpod 공식문서 읽어보기 (1) Make your first provider/network request (0) | 2025.03.10 |
---|---|
하단버튼 키보드가 가리지 않게 이동시키기 (0) | 2025.03.05 |
bloc 상태관리에서 forEach와 onEach의 차이점 (0) | 2025.03.04 |
플러터에 지역화 기능 넣어주는 방법 (1) | 2025.03.03 |
다른 ios 계정 프로젝트에 내 아이폰 기기 등록하기 (0) | 2025.03.01 |