点击出现对应的option,一行展示四个标签
import 'package:flutter/material.dart';
class TemplateFilter extends StatefulWidget {
const TemplateFilter({Key? key}) : super(key: key);
State<TemplateFilter> createState() => _TemplateFilterState();
}
class _TemplateFilterState extends State<TemplateFilter> {
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 28.0, vertical: 6.0),
child: const Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
FilterOption(title: '排序规则', options: ['最新', '最热', '最新', '最热']),
FilterOption(title: '主题风格', options: ['全网爆款', '男', '女', '大片', '是', '职场', '最美证件照']),
FilterOption(title: '是否可用', options: ['免费', '收费']),
],
),
);
}
}
class FilterOption extends StatefulWidget {
final String title;
final List<String> options;
const FilterOption({Key? key, required this.title, required this.options})
: super(key: key);
State<FilterOption> createState() => _FilterOptionState();
}
class _FilterOptionState extends State<FilterOption> {
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => showFilterOptions(context),
child: Row(
children: [
Text(widget.title, style: const TextStyle(color: Color(0xffaaaaaa))),
const Icon(Icons.keyboard_arrow_down_sharp, color: Color(0xffaaaaaa)),
],
),
);
}
void showFilterOptions(BuildContext context) {
final RenderBox button = context.findRenderObject()! as RenderBox;
final RenderBox overlay =
Navigator.of(context).overlay!.context.findRenderObject()! as RenderBox;
Offset offset = Offset(0.0, button.size.height);
RelativeRect position = RelativeRect.fromRect(
Rect.fromPoints(
button.localToGlobal(offset, ancestor: overlay),
button.localToGlobal(button.size.bottomRight(Offset.zero) + offset, ancestor: overlay),
),
Offset.zero & overlay.size,
);
double screenWidth = MediaQuery.of(context).size.width;
showMenu(
color: const Color(0xff1c1c1c),
context: context,
position: position,
constraints: BoxConstraints(maxWidth: screenWidth),
items: [
PopupMenuItem(
child: Container(
width: screenWidth,
alignment: AlignmentDirectional.topStart,
child: Wrap(
alignment: WrapAlignment.start, // 从左侧开始排列
spacing: 8.0, // 控制按钮之间的间距
children: widget.options.map((option) => SizedBox(
width: 80.0, // 固定按钮宽度
child: TextButton(
onPressed: () => print('Button 1'),
style: TextButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
backgroundColor: const Color(0xff2c2c2c),
),
child: Text(
option,
style: const TextStyle(color: Colors.white, fontSize: 12),
),
),
)).toList(),
),
),
),
],
);
}
}
参考:https://blog.csdn.net/gzx110304/article/details/134069921