上一篇, 介绍了如何便利的构造一个自己的点击控件


flutter 中 如果给图片外面套 InkWell ,你会发现点击的逻辑生效了,但是 UI 上没反应

备注: 图片来源, 违反版权请联系我,删除

p

代码如下

import 'package:flutter/material.dart';

class ImageTapWidget extends StatefulWidget {
  final Widget child;
  final Function onTap;

  const ImageTapWidget({Key key, this.child, this.onTap}) : super(key: key);

  @override
  ImageTapWidgetState createState() {
    return new ImageTapWidgetState();
  }
}

class ImageTapWidgetState extends State<ImageTapWidget> {
  var isDown = false;
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      child: AnimatedContainer(
        duration: Duration(milliseconds: 500),
        foregroundDecoration: BoxDecoration(
          color: isDown ? Colors.white.withOpacity(0.5) : Colors.transparent,
        ),
        child: widget.child,
      ),
      onTap: widget.onTap,
      onTapDown: (d) => setState(() => this.isDown = true),
      onTapUp: (d) => setState(() => this.isDown = false),
      onTapCancel: () => setState(() => this.isDown = false),
    );
  }
}

利用 Container 的前景色完成点击色的变化

利用 AnimatedContainer 完成颜色的过度

这样就完成了一个有点击效果的控件,当然这个控件的效果不止于对图片有效,对所有的控件都有效,但是正常来说我对于其他类型的控件应该不需要做这个操作

点击效果过快

当然,有的时候你会遇到点击和松开之间过快,造成了视觉上没点击的感觉,这种情况下可以使用另一种方法,利用动画的方式来实现

截图

import 'package:flutter/material.dart';

class ImageTapWidget extends StatefulWidget {
  final Widget child;
  final Function onTap;

  const ImageTapWidget({Key key, this.child, this.onTap}) : super(key: key);

  @override
  ImageTapWidgetState createState() {
    return new ImageTapWidgetState();
  }
}

class ImageTapWidgetState extends State<ImageTapWidget> with SingleTickerProviderStateMixin {
  AnimationController _ctl;

  @override
  void initState() {
    super.initState();
    _ctl = AnimationController(vsync: this, duration: Duration(milliseconds: 200));
  }

  @override
  void dispose() {
    _ctl.stop();
    _ctl.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      child: AnimatedBuilder(
        animation: _ctl,
        builder: (BuildContext context, Widget child) {
          return Container(
            foregroundDecoration: BoxDecoration(
              color: Colors.white.withOpacity(0.5 * _ctl.value),
            ),
            child: widget.child,
          );
        },
      ),
      onTap: widget.onTap,
      onTapDown: (d) => _ctl.forward(),
      onTapUp: (d) => prepareToIdle(),
      onTapCancel: () => prepareToIdle(),
    );
  }

  void prepareToIdle() {
    AnimationStatusListener listener;
    listener = (AnimationStatus statue) {
      if (statue == AnimationStatus.completed) {
        _ctl.removeStatusListener(listener);
        toStart();
      }
    };
    _ctl.addStatusListener(listener);
    if (!_ctl.isAnimating) {
      _ctl.removeStatusListener(listener);
      toStart();
    }
  }

  void toStart() {
    _ctl.stop();
    _ctl.reverse();
  }
}

创建一个AnimationBuilder结合 AnimationController 来实现

在按下的时候执行动画, 然后在抬起或取消的时候也先不结束动画,而是监听动画状态,等待动画完成再执行动画效果上的取消动画

后记

点击效果相关的简单实现就在这里了,有不明白的可以留言哦