89 lines
3.0 KiB
Dart
89 lines
3.0 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'highlight_text.dart';
|
|
|
|
// 자동완성 드롭다운 공통 위젯
|
|
class AutocompleteDropdown extends StatelessWidget {
|
|
// 드롭다운에 표시할 항목 리스트
|
|
final List<String> items;
|
|
// 현재 입력된 텍스트(하이라이트 기준)
|
|
final String inputText;
|
|
// 항목 선택 시 콜백
|
|
final void Function(String) onSelect;
|
|
// 드롭다운 표시 여부
|
|
final bool showDropdown;
|
|
// 최대 높이(항목 개수에 따라 자동 조절)
|
|
final double maxHeight;
|
|
// 드롭다운이 비었을 때 표시할 위젯
|
|
final Widget emptyWidget;
|
|
|
|
const AutocompleteDropdown({
|
|
Key? key,
|
|
required this.items,
|
|
required this.inputText,
|
|
required this.onSelect,
|
|
required this.showDropdown,
|
|
this.maxHeight = 200,
|
|
this.emptyWidget = const Padding(
|
|
padding: EdgeInsets.all(12.0),
|
|
child: Text('검색 결과가 없습니다'),
|
|
),
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return AnimatedContainer(
|
|
duration: const Duration(milliseconds: 200),
|
|
height:
|
|
showDropdown
|
|
? (items.length > 4 ? maxHeight : items.length * 50.0)
|
|
: 0,
|
|
margin: EdgeInsets.only(top: showDropdown ? 4 : 0),
|
|
child: SingleChildScrollView(
|
|
physics: const ClampingScrollPhysics(),
|
|
child: GestureDetector(
|
|
onTap: () {}, // 이벤트 버블링 방지
|
|
child: Container(
|
|
width: double.infinity,
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(4),
|
|
border: Border.all(color: Colors.grey.shade300),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.grey.withAlpha(77),
|
|
spreadRadius: 1,
|
|
blurRadius: 3,
|
|
offset: const Offset(0, 1),
|
|
),
|
|
],
|
|
),
|
|
child:
|
|
items.isEmpty
|
|
? emptyWidget
|
|
: ListView.separated(
|
|
shrinkWrap: true,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
itemCount: items.length,
|
|
separatorBuilder:
|
|
(context, index) =>
|
|
Divider(height: 1, color: Colors.grey.shade200),
|
|
itemBuilder: (context, index) {
|
|
final String item = items[index];
|
|
return ListTile(
|
|
dense: true,
|
|
title: HighlightText(
|
|
text: item,
|
|
highlight: inputText,
|
|
highlightColor: Theme.of(context).primaryColor,
|
|
),
|
|
onTap: () => onSelect(item),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|