其他分享
首页 > 其他分享> > Flutter-Ink家族

Flutter-Ink家族

作者:互联网

概述

Ink翻译为墨水,墨汁的意思,就是点击某一组件时具有水波纹的效果。Android中MaterialButton中有类似的效果,Flutter中和Ink相关的有Ink、InkWell、InkFeature、Ink.image、InkSplash、InkRipple、InkResponse、InkDecoration、InkHighlight,有些是组件,有些是效果,有些是属性。

Ink

Ink的构造如下:

  Ink({
    Key? key,
    this.padding,
    Color? color,
    Decoration? decoration,
    this.width,
    this.height,
    this.child,
  }) 

Ink和Container最大的不同在于使用InkWell时,Ink可以展示点击出现的水波纹的效果,而Contaier没有任何点击效果。除此之外,Ink和Container相似,只是比Container少了一些参数而已,若无明确指明,官方和民间都建议使用Container。Ink一般搭配InkWell使用,主要是设置InkWell的样式。decoration和Container中的decoration一样,使用BoxDecoration就好,若BoxDecoration不是很清楚,可以看看Flutter-Container详解

效果说明
在这里插入图片描述没有使用decoration
在这里插入图片描述使用decoration设置圆角
在这里插入图片描述使用Container

通过观察效果图可以发现,使用Container确实无法展示InkWell的点击效果。当使用decoration设置圆角的时候,虽然按钮形状是由圆角的,但水波纹扩散的范围依然是矩形,想要使水波纹扩散的范围是圆角矩阵,在InkWell中把borderRadius的圆角弧度设置为和decoration中圆角弧度一致即可。当在decoration中设置了color,InkWell中自带的color就不要设置了,否则报错。

InkWell,InkResponse

class InkWell extends InkResponse {  ...   }

InkWell属于完全继承InkResponse,没有一点自己属于自己的属性,只是比InkResponse 少了一些属性,估计那些属性不常用,所以InkWell相对简单,才会导致InkWell使用的比较多,而InkResponse使用的相对较少吧。InkResponse的构造如下:

  const InkResponse({
    Key? key,
    this.child,
    this.onTap,
    this.onTapDown,
    this.onTapCancel,
    this.onDoubleTap,
    this.onLongPress,
    this.onHighlightChanged,
    this.onHover,
    this.mouseCursor,
    this.containedInkWell = false,
    this.highlightShape = BoxShape.circle,
    this.radius,
    this.borderRadius,
    this.customBorder,
    this.focusColor,
    this.hoverColor,
    this.highlightColor,
    this.overlayColor,
    this.splashColor,
    this.splashFactory,
    this.enableFeedback = true,
    this.excludeFromSemantics = false,
    this.focusNode,
    this.canRequestFocus = true,
    this.onFocusChange,
    this.autofocus = false,
  })

下表则对其中属性一一进行说明和比较:

属性说明
child子组件
onTap点击
onTapDown按下
onTapCancel点击取消
onDoubleTap双击
onLongPress长按
onHighlightChanged高亮色变化
onHover悬停改变
mouseCursor光标
containedInkWell范围裁切
highlightShape高亮色形状
radius水波纹半径
borderRadius边框弧度
customBorder边框
focusColor焦点色
hoverColor悬停色
highlightColor高亮色
overlayColor覆盖色
splashColor散点色
splashFactorysplash形状
enableFeedback是否反馈
excludeFromSemantics是否删除语义
focusNode焦点结点
canRequestFocus是否可以请求焦点
onFocusChange焦点改变
autofocus自动获取焦点

针对这些属性直接翻译很多不通顺,也不好说清楚,没有效果图直观,下面则对部分属性进行效果展示

属性效果
InkSplash.splashFactory在这里插入图片描述
InkRipple.splashFactory在这里插入图片描述

InkSplash.splashFactory 和InkRipple.splashFactory不同之处可能在于水波纹的开始及结束状态。

属性效果
true在这里插入图片描述
false在这里插入图片描述

containedInkWell 设为true时,超出容器的水波纹会被裁剪,false的时候不会被裁剪。

-radius,borderRadius
当水波纹为圆形的时候,radius为水波纹半径。borderRadius为InkWell或InkResponse的边框圆角,当设置后水波纹扩散有角的地方,会被才切成有弧度的,而不是以直角的显示:

属性效果
radius: 22.0在这里插入图片描述
radius: 66.0在这里插入图片描述
borderRadius: BorderRadius.circular(16.0),radius: 66.0在这里插入图片描述

radius值不同,水波纹的半径是有区别的。borderRadius需要仔细观察第二幅和第三幅图,在点击的时候,四角是否有灰色的直角背景显示出来,如果有就没有设置,如果没有就是设置了。

InkFeature、Ink.image、InkSplash、InkRipple、InkDecoration、InkHighlight

    if (_ink == null) {
      _ink = InkDecoration(
        decoration: widget.decoration,
        configuration: createLocalImageConfiguration(context),
        controller: Material.of(context)!,
        referenceBox: context.findRenderObject()! as RenderBox,
        onRemoved: _handleRemoved,
      );
    } else {
      _ink!.decoration = widget.decoration;
      _ink!.configuration = createLocalImageConfiguration(context);
    }

InkDecoration直接将Ink中设置的decoration进一步包装,添加一些配置。

  Ink.image({
    Key? key,
    this.padding,
    required ImageProvider image,
    ImageErrorListener? onImageError,
    ColorFilter? colorFilter,
    BoxFit? fit,
    AlignmentGeometry alignment = Alignment.center,
    Rect? centerSlice,
    ImageRepeat repeat = ImageRepeat.noRepeat,
    bool matchTextDirection = false,
    this.width,
    this.height,
    this.child,
  })

观察发现,Ink.image和BoxDecoration中的image指定的DecorationImage是一模一样,用法也一样。若不太清楚,可以参考Flutter-Container详解

class _InkRippleFactory extends InteractiveInkFeatureFactory {
  const _InkRippleFactory();
  
  @override
  InteractiveInkFeature create({
    required MaterialInkController controller,
    required RenderBox referenceBox,
    required Offset position,
    required Color color,
    required TextDirection textDirection,
    bool containedInkWell = false,
    RectCallback? rectCallback,
    BorderRadius? borderRadius,
    ShapeBorder? customBorder,
    double? radius,
    VoidCallback? onRemoved,
  }) {
    return InkRipple(
      controller: controller,
      referenceBox: referenceBox,
      position: position,
      color: color,
      containedInkWell: containedInkWell,
      rectCallback: rectCallback,
      borderRadius: borderRadius,
      customBorder: customBorder,
      radius: radius,
      onRemoved: onRemoved,
      textDirection: textDirection,
    );
  }
}
...
  /// Used to specify this type of ink splash for an [InkWell], [InkResponse]
  /// or material [Theme].
  static const InteractiveInkFeatureFactory splashFactory = _InkRippleFactory();
  ...

所以InkSplash、InkRipple是上文中提到的InkSplash.splashFactory 和InkRipple.splashFactory工厂具体实现。
工厂模式就是定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行,主要解决接口选择的问题,是 Java 中最常用的设计模式之一。在任何需要生成复杂对象的地方,都可以使用工厂方法模式。复杂对象适合使用工厂模式,而简单对象只需简单通过构造创建对象即可,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。

Flutter中IButton、BottomNavigationBar、CalendarDatePicker、DataTable、NavigationRail、Stepperden等使用了InkResponse或InkWell,所以很多组件也有水波纹效果。

文中有一些错误、遗漏和不准确,欢迎批评指正。

标签:水波纹,InkResponse,InkWell,家族,decoration,点击,Ink,Flutter
来源: https://blog.csdn.net/qq_34202054/article/details/116020015