android中,所有View都可以直接setOnClickListener,
RN中也有TouchableHightlight这样的控件可以直接套在外面,ios中也可以有UIControl 这样的控件可以直接添加点击事件.

那么flutter中有吗? 答案自然是有. GestureDetector,InkResponse,InkWell,
包括一些琳琅满目的按钮,比如FlatButton,MaterialButton,CupertinoButton,IconButton,ImageButton
这些组件都可以达到目的. 那么自定义的目的是什么呢?

<>自定义的优点

最重要的自然就是可控性强,复用性强. 一次修改终身受用.
来看下面的这段代码
import 'package:flutter/material.dart'; class MaterialTapWidget extends
StatelessWidget { final double radius; final Function onTap; final Widget child;
final double elevation; final Color backgroundColor; final Color splashColor;
final Function onLongTap; const MaterialTapWidget({ Key key, this.radius = 0.0,
this.onTap, this.onLongTap, @required this.child, this.splashColor, this.
elevation= 0.0, this.backgroundColor = Colors.transparent, }) : super(key: key);
@override Widget build(BuildContext context) { Widget w = ClipRRect(
borderRadius: BorderRadius.circular(radius), child: Material( borderRadius:
BorderRadius.circular(radius), color: backgroundColor, elevation: 0.0, child:
InkWell( child: child, onTap: onTap, onLongPress: onLongTap, ), ), ); if (this.
splashColor!= null) { return Theme( data: Theme.of(context).copyWith(splashColor
: this.splashColor), child: w, ); } return w; } }


一共有下面几个属性
final double radius; //圆角 final Function onTap; //点击回调 final Widget child; //
内部的控件 final double elevation; //阴影"高度" final Color backgroundColor; //背景颜色 final
Color splashColor; // 点击的水波纹颜色 final Function onLongTap; //长按回调
这个在日常开发中可以满足我的需求了,但是有一天我还需要单独设置其他的呢 比如我需要添加双击事件,那么我只需要修改几处地方
class MaterialTapWidget extends StatelessWidget { final double radius; final
Function onTap; final Widget child; final double elevation; final Color
backgroundColor; final Color splashColor; final Function onLongTap; final
Function onDoubleTap; //添加字段 const MaterialTapWidget({ Key key, this.radius =
0.0, this.onTap, this.onLongTap, @required this.child, this.splashColor, this.
elevation= 0.0, this.backgroundColor = Colors.transparent, this.onDoubleTap,
//添加构造方法 }) : super(key: key); @override Widget build(BuildContext context) {
Widget w= ClipRRect( borderRadius: BorderRadius.circular(radius), child:
Material( borderRadius: BorderRadius.circular(radius), color: backgroundColor,
elevation: 0.0, child: InkWell( child: child, onTap: onTap, onDoubleTap:
onDoubleTap, //添加控件回调 onLongPress: onLongTap, ), ), ); if (this.splashColor !=
null) { return Theme( data: Theme.of(context).copyWith(splashColor: this.
splashColor), child: w, ); } return w; } }
这样就完成了双击的支持, 同样的,如果有别的需求也可以往这里放

比如我们有了特殊需求,希望如果设备是ios设备,则不使用Material风格,而使用一个点击背景变色的风格

在整体项目是使用MaterialApp的情况下,可以像下面这样写
import 'package:flutter/material.dart'; class PlatformTapWidget extends
StatefulWidget { final double radius; final Function onTap; final Widget child;
final double elevation; final Color backgroundColor; final Color splashColor;
final Function onLongTap; const PlatformTapWidget({ Key key, this.radius = 0.0,
this.onTap, this.elevation, this.backgroundColor = Colors.white, this.
splashColor, this.onLongTap, this.child, }) : super(key: key); @override
_PlatformTapWidgetStatecreateState() => _PlatformTapWidgetState(); } class
_PlatformTapWidgetState extends State<PlatformTapWidget> { bool isDown = false;
@override Widget build(BuildContext context) { Color splashColor = widget.
splashColor?? Colors.grey.withOpacity(0.3); if (Theme.of(context).platform ==
TargetPlatform.iOS) { Widget w; w = ClipRRect( borderRadius: BorderRadius.
circular(widget.radius), child: GestureDetector( behavior: HitTestBehavior.
translucent, onTap: widget.onTap, onTapDown: (d) => setState(() => this.isDown =
true), onTapUp: (d) => setState(() => this.isDown = false), onTapCancel: () =>
setState(() => this.isDown = false), child: AnimatedContainer( duration:
Duration(milliseconds: 600), curve: Curves.easeIn, color: isDown ? splashColor :
widget.backgroundColor, child: widget.child, ), ), ); return w; } Widget w =
ClipRRect( borderRadius: BorderRadius.circular(widget.radius), child: Material(
borderRadius: BorderRadius.circular(widget.radius), color: widget.
backgroundColor, elevation: 0.0, child: InkWell( child: widget.child, onTap:
widget.onTap, onLongPress: widget.onLongTap, ), ), ); if (widget.splashColor !=
null) { return Theme( data: Theme.of(context).copyWith(splashColor: widget.
splashColor), child: w, ); } return w; } }
这样就可以达到ios设备和android设备不同的方法

而这个也很符合flutter 的设计理念, 组合优于继承 ,使用flutter自带的组件 通过组合的方式构建出自己的组件

flutter中可以有很多这样的组合方式

比如我项目中有大量左图片,右文字的按钮,并且按钮的图片大小是固定的,字体大小也固定,并且附带圆角
那么这种情况下可以自己封装一个控件
import 'package:flutter/material.dart'; import
'package:platform_widget_demo/widgets/platform_tap_widget.dart'; class
IconTextButton extends StatelessWidget { final IconData icon; final String text;
final Function onTap; const IconTextButton({ Key key, this.icon, this.text, this
.onTap, }) : super(key: key); @override Widget build(BuildContext context) {
return PlatformTapWidget( onTap: onTap, child: Row( children: <Widget>[ Icon(
icon), Text(text), ], ), ); } } IconTextButton( icon: Icons.scanner, text: "扫描",
),