// thêm mới drop tự làm
class MyDropDown extends StatefulWidget {
final List<DanhMucDoiTuongModel> list;
final String label;
final TextEditingController controller;
final String? initValue;
final Function(String) callback;
bool? searchName = true;
double? heightDrop;
MyDropDown(
{super.key,
required this.list,
required this.label,
required this.controller,
required this.initValue,
required this.callback,
this.searchName,
this.heightDrop});
@override
State<MyDropDown> createState() => _MyDropDownState();
}
class _MyDropDownState extends State<MyDropDown> {
List<DanhMucDoiTuongModel> searchList = [];
final LayerLink _layerLink = LayerLink();
double? _buttonWidth;
var overlayController = OverlayPortalController();
var tempLabel = ""; // tên hiển thị khi chọn 1 item
@override
void initState() {
searchList = widget.list;
if (widget.initValue == null) {
tempLabel = widget.label;
} else {
tempLabel = widget.list
.firstWhere((element) => element.ID == widget.initValue)
.Ten;
}
super.initState();
}
@override
Widget build(BuildContext context) {
return CompositedTransformTarget(
link: _layerLink,
child: InkWell(
onTap: () {
toggleDrop();
},
child: OverlayPortal(
controller: overlayController,
overlayChildBuilder: (context) {
log(_buttonWidth.toString());
return CompositedTransformFollower(
link: _layerLink,
targetAnchor: Alignment.bottomLeft,
child: LimitedBox(
maxWidth: _buttonWidth!,
maxHeight: widget.heightDrop ?? 200,
child: SingleChildScrollView(
child: Card(
elevation: 8,
color: Colors.white,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.only(top: 7),
child: SizedBox(
height: 40,
child: TextField(
onChanged: (text) {
if (text.isNotEmpty) {
if (widget.searchName!) {
setState(() {
searchList = widget.list
.where((e) => e.Ten.toUpperCase()
.contains(text.toUpperCase()))
.toList();
});
} else {
setState(() {
searchList = widget.list
.where((e) => e.Ma.toUpperCase()
.contains(text.toUpperCase()))
.toList();
});
}
} else {
setState(() {
searchList = widget.list;
});
}
},
controller: widget.controller,
decoration: InputDecoration(
labelText: "Tìm ...",
contentPadding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 8,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
),
),
),
),
LimitedBox(
maxHeight: widget.heightDrop == null
? 150
: (widget.heightDrop! - 50),
child: ListView.builder(
shrinkWrap: true,
itemCount: searchList.length,
itemBuilder: (context, index) {
var curItem = searchList[index];
return InkWell(
onTap: () {
setState(() {
widget.callback(curItem.ID);
tempLabel = curItem.Ten;
searchList = widget.list;
toggleDrop();
// _isOpen = false;
// hideOverlay();
});
},
child: MyItemDrop(curItem: curItem),
);
}),
)
],
),
),
),
),
),
);
},
child: MyButtonDrop(label: tempLabel, onTap: toggleDrop)),
),
);
}
toggleDrop() {
_buttonWidth = context.size?.width;
overlayController.toggle();
}
}
class MyButtonDrop extends StatelessWidget {
final String label;
final Function() onTap;
const MyButtonDrop({super.key, required this.label, required this.onTap});
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onTap,
child: Container(
height: 50,
decoration: BoxDecoration(
border: Border.all(), borderRadius: BorderRadius.circular(10)),
child: Row(
children: [Text(label), const Icon(Icons.arrow_drop_down)],
),
),
);
}
}
class MyItemDrop extends StatelessWidget {
final DanhMucDoiTuongModel curItem;
const MyItemDrop({super.key, required this.curItem});
@override
Widget build(BuildContext context) {
return Card(
child: SizedBox(
height: 40,
child: Padding(
padding: const EdgeInsets.only(left: 10, top: 10),
child: Text(curItem.Ten),
),
),
);
}
}
我看这篇文章来做到这一点https://medium.com/snapp-x/creating-custom-dropdowns-with-overlayportal-in-flutter-4f09b217cfce 仍然不知道为什么它没有收到我的价值传递?我该怎么做? 已经在覆盖层中选择了按钮,我在 AlertDialog 中调用这个小部件 尝试在 YouTube 上搜索,但对我来说没有任何作用
LimitedBox
仅在不受约束时限制其大小。您需要用 CompositedTransformFollower
包裹您的 UnconstrainedBox
。