另一个答案是做到这一点的最佳方法,但根据评论中OP的要求,这里有两种非常“hacky”的方法来实现这一点,但没有实现自定义小部件。
1. 访问DropdownButton
直接使用widget树GlobalKey
如果我们看一下源代码DropdownButton
,我们可以注意到它使用GestureDetector
处理水龙头。然而,它不是直系后代DropdownButton
,并且我们不能依赖其他小部件的树结构,因此找到检测器的唯一合理稳定的方法是递归搜索。
一个例子胜过一千种解释:
class DemoDropdown extends StatefulWidget {
@override
InputDropdownState createState() => DemoDropdownState();
}
class DemoDropdownState<T> extends State<DemoDropdown> {
/// This is the global key, which will be used to traverse [DropdownButton]s widget tree
GlobalKey _dropdownButtonKey;
void openDropdown() {
GestureDetector detector;
void searchForGestureDetector(BuildContext element) {
element.visitChildElements((element) {
if (element.widget != null && element.widget is GestureDetector) {
detector = element.widget;
return false;
} else {
searchForGestureDetector(element);
}
return true;
});
}
searchForGestureDetector(_dropdownButtonKey.currentContext);
assert(detector != null);
detector.onTap();
}
@override
Widget build(BuildContext context) {
final dropdown = DropdownButton<int>(
key: _dropdownButtonKey,
items: [
DropdownMenuItem(value: 1, child: Text('1')),
DropdownMenuItem(value: 2, child: Text('2')),
DropdownMenuItem(value: 3, child: Text('3')),
],
onChanged: (int value) {},
);
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Offstage(child: dropdown),
FlatButton(onPressed: openDropdown, child: Text('CLICK ME')),
],
);
}
}
2. Use Actions.invoke
Flutter 最近的功能之一是Actions
(我不知道它的意思是什么,我今天才注意到它flutter upgrade
), and DropdownButton
用它来对不同的……嗯,动作做出反应。
因此,触发按钮的稍微不那么麻烦的方法是找到上下文Actions
小部件并调用必要的操作。
这种方法有两个优点:首先,Actions
widget 在树中的位置稍高一些,因此遍历该树不会像使用那样长GestureDetector
, 其次,Actions
似乎是比手势检测更通用的机制,因此它不太可能从DropdownButton
将来。
// The rest of the code is the same
void openDropdown() {
_dropdownButtonKey.currentContext?.visitChildElements((element) {
if (element.widget is Semantics) {
element.visitChildElements((element) {
if (element.widget is Actions) {
element.visitChildElements((element) {
Actions.invoke(element, ActivateIntent());
});
}
});
}
});
}