我想创建一个按钮来打开菜单来选择一个项目。但我希望菜单不是弹出式的,而是构建在按钮下。请参阅设计以供参考。
有图书馆可以做到这一点吗?或者我应该从头开始编程?
有像“DropdownButton2”和“DropdownButton”这样的小部件,将小部件菜单显示为弹出窗口。我想要同样的东西,但它显示了按钮下构建的菜单中的元素并占用空间,并且不覆盖菜单下的其他元素,如设计。
您可以在这个设计中看到菜单不是弹出式的。
不幸的是,似乎没有一个流行的库可以做到这一点。此设计可以使用 ExpansionTile 来实现 — 事实证明,使用
ExpansionTile
比使用 ExpansionPanel
更容易,因为后者必须与 ExpansionPanelList
一起使用,而在默认的 Material 设计之外很难进行自定义。
这是一个尽可能接近您的设计的示例实现,您可以对其进行更改以满足您的需求。
class ExpandingMenu extends StatefulWidget {
final List<String> menuOptions;
const ExpandingMenu({super.key, required this.menuOptions});
@override
State<ExpandingMenu> createState() => _ExpandingMenuState();
}
class _ExpandingMenuState extends State<ExpandingMenu> {
String? _selectedOption;
final _controller = ExpansionTileController();
bool _isExpanded = false;
@override
Widget build(BuildContext context) {
final outlineColor = Theme.of(context).colorScheme.outlineVariant;
return Theme(
data: Theme.of(context).copyWith(
// This is required to remove the default dividers around the
// ExpansionTile
dividerColor: Colors.transparent,
),
child: ExpansionTile(
showTrailingIcon: false,
tilePadding: EdgeInsets.zero,
controller: _controller,
onExpansionChanged: (value) => setState(() => _isExpanded = value),
title: Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
border: Border.all(
color: _isExpanded ? Colors.lightBlueAccent : outlineColor,
width: 2,
),
borderRadius: BorderRadius.circular(5),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
_selectedOption ?? 'Vorlage aussuchen',
style: TextStyle(
color: (_isExpanded || _selectedOption != null)
? Colors.black
: Colors.grey,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
Transform.rotate(
angle: pi / 2,
child: const Icon(
Icons.chevron_right_rounded,
color: Colors.lightBlueAccent,
),
),
],
),
),
children: [
Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
border: Border.all(
color: outlineColor,
width: 2,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
for (String option in widget.menuOptions)
GestureDetector(
onTap: () => setState(() {
_selectedOption = option;
_controller.collapse();
}),
child: Text(
option,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
].expand((e) => [e, const Divider(height: 20)]).toList()
..removeLast(), // Remove the trailing divider
),
),
],
),
);
}
}
就你而言:
ExpandingMenu(
menuOptions: ['keine Auswahl', 'Vorlage 1', 'Vorlage 2'],
)
我见过的大多数库都会在其他内容上弹出,因此您可能需要从头开始构建一些东西。
构建这样的东西应该不会太难。您可以构建一个显示/隐藏内容的自定义小部件,也可以将这些选项放在 ExpansionPanel
中