一般来说,非Button
类的组件需要通过向外添加一层GestureDetector
来添加点击事件,会增加布局的层次,在嵌套多重布局的情况下,移动组件树也比较麻烦。
// 原生添加点击事件的方法
GestureDetector(
child: widget,
onTap: () {
// 点击事件
},
);
可以通过启用Dart
的扩展方法来优化点击事件,在组件的扩展方法中返回已经嵌套了GestureDetector
的组件。
优化
注: 除Button
外的组件
// 定义扩展方法
Widget withTap(GestureTapCallback onTap) {
return GestureDetector(
child: this,
onTap: onTap,
);
}
// 使用
widget.withTap((){
// 点击事件
});
因为Button
的onPress
是final
,并只能在其构造方法设置,但因为不用嵌套多层代码,也可以选择不优化,也可以创建自定义组件来封装。
或者自定义组件中只想暴露其子组件的点击事件,而非其完整组件的点击是事件,则可以通过mixins
语法来优化。
// 定义mixins
class TapWidget {
GestureTapCallback tapCallback;
}
class MyWidget extends StatelessWidget with TapWidget{
@override
Widget build(BuildContext context) {
// 将tapCallback设置为某个widget的点击事件
var mywidget = newWidget(context);
return mywidget.withTap(tapCallback);
}
}
// 优化扩展方法
Widget withTap(GestureTapCallback onTap) {
if (this is TapWidget) {
var widget = this as TapWidget;
widget.tapCallback = onTap;
return this;
}
return GestureDetector(
child: this,
onTap: onTap,
);
}
// 使用,和非自定义组件一样
myWidget.withTap((){
// 点击事件
});
如果添加水波纹特效则可以通过修改扩展方法来添加一层InkWell
组件来实现,比较简单。
其实不仅仅是点击事件,其他触摸事件等交互事件或者添加外饰组件也可以通过这种方法来实现,Flutter也有类似的第三方库来实现这种封装。
虽然这种扩展方法的实现虽然优化了点击事件的处理,减少了布局嵌套的层次,但是是通过破坏了Flutter直观性的布局结构实现的,在代码层次中,将点击事件由一个组件改为了一个方法,有可能会造成误导,需要谨慎使用。