Flutter widget点击事件和点击态

作者: TryEnough | 来源:发表于2019-01-18 00:02 被阅读9次

    原文链接

    http://tryenough.com/flutter06

    跟多教程

    http://tryenough.com/type-flutter

    你将学到

    1.使用Flutter自定义控件点击态处理
    2.Flutter 添加点击手势
    3.Flutter 多状态管理
    4.一个具体的例子

    先看下效果

    效果图分析:

    • 点击不放开的时候,控件四周出现一个深蓝色的边框
    • 放开点击控件颜色会改变颜色,active状态绿色,inactive灰色

    实现过程

    首先你需要知道的是:

    我们处理手势可以使用GestureDetector组件,它是可以添加手势的一个widget,观察它的源码:

    class GestureDetector extends StatelessWidget {
      GestureDetector({
        Key key,
        this.child,
        this.onTapDown,
        this.onTapUp,
        this.onTap,
        this.onTapCancel,
        this.onDoubleTap,
        this.onLongPress,
        this.onLongPressUp,
        this.onVerticalDragDown,
        this.onVerticalDragStart,
        this.onVerticalDragUpdate,
        this.onVerticalDragEnd,
        this.onVerticalDragCancel,
        this.onHorizontalDragDown,
        this.onHorizontalDragStart,
        this.onHorizontalDragUpdate,
        this.onHorizontalDragEnd,
        this.onHorizontalDragCancel,
        this.onPanDown,
        this.onPanStart,
        this.onPanUpdate,
        this.onPanEnd,
        this.onPanCancel,
        this.onScaleStart,
        this.onScaleUpdate,
        this.onScaleEnd,
        this.behavior,
        this.excludeFromSemantics = false
      })
    ...
    
    

    可以看到GestureDetector的本质就是一个普通的widget,它拥有很多的手势onTapDown(点下),onTapUp(抬起),onTap(点击)...等,同时也拥有child属性,我们可以利用child绘制界面,利用手势处理点击事件。

    首先画出界面的样子:

    1.用一个多状态的widget来表示方框,如下:

    class TapboxC extends StatefulWidget {
      TapboxC({Key key, this.active: false, @required this.onChanged})
          : super(key: key);
    
      final bool active;   // 分析1
      final ValueChanged<bool> onChanged;  //分析2  先跳过
    
      _TapboxCState createState() => _TapboxCState();
    }
    

    分析:

    • 分析1:active保存当前的状态
    • 分析2:作为点击事件(onTap),先跳过

    2. 实现TapboxC类的状态类_TapboxCState:

    你需要提前知道的是:

    a. 通过 用Flutter定义stateFul控件 这篇文章,我们知道需要为自定义StatefulWidget实现一个状态state类来处理状态,如果你还没学习过这篇文章,可以先记住这个规则。

    b. 调用**setState **方法会触发控件重新绘制

    实现状态类:

    class _TapboxCState extends State<TapboxC> {
      bool _highlight = false;
    
      void _handleTapDown(TapDownDetails details) { //定义点击函数
        setState(() {
          _highlight = true; //手指按下时将_highlight设置为true
        });
      }
    
      void _handleTapUp(TapUpDetails details) {
        setState(() {
          _highlight = false;
        });
      }
    
      void _handleTapCancel() {
        setState(() {
          _highlight = false;
        });
      }
    
      void _handleTap() {
        widget.onChanged(!widget.active);  //先跳过 实现
      }
    
      Widget build(BuildContext context) {
        return GestureDetector(
          onTapDown: _handleTapDown, // 分析 1
          onTapUp: _handleTapUp, 
          onTap: _handleTap,
          onTapCancel: _handleTapCancel,
          child: Container(
            child: Center(
              child: Text(widget.active ? 'Active' : 'Inactive',   // 分析 2
                  style: TextStyle(fontSize: 32.0, color: Colors.white)),
            ),
            width: 200.0,
            height: 200.0,
            decoration: BoxDecoration(
              color:
              widget.active ? Colors.lightGreen[700] : Colors.grey[600], //分析3
              border: _highlight  // 分析 4
                  ? Border.all(
                color: Colors.teal[700],
                width: 10.0,
              )
                  : null,
            ),
          ),
        );
      }
    }
    

    分析:

    • 分析1: 处理点击事件的顺序是:down, up, tap, cancel
    • 分析2: 根据active的值显示不同的文字
    • 分析3: 根据active的值显示不同的背景色
    • 分析4: 当_highlight的值为true时显示边框,否则不显示

    上面代码中,在点击事件中修改了_highlight的值(代表是否需要高亮),在build方法绘制中Text:根据active的值显示不同的文字和背景色,BoxDecoration:根据是否_highlight=true绘制边框(border)。

    上面我们先跳过了_handleTap点击方法中调用的onChanged方法,接下来我们来看一下它的实现:

    class ParentWidget extends StatefulWidget {
      @override
      _ParentWidgetState createState() => _ParentWidgetState();
    }
    
    class _ParentWidgetState extends State<ParentWidget> {
      bool _active = false;
    
      void _handleTapboxChanged(bool newValue) {
        setState(() {
          _active = newValue;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Container(
          child: TapboxC(
            active: _active,
            onChanged: _handleTapboxChanged,  //分析1
          ),
        );
      }
    }
    

    分析:
    分析1: 可以看到,这里是将_handleTapboxChanged方法作为参数传递给了上面定义的TapboxC。然后在TapboxC的点击事件中,触发了_handleTapboxChanged方法中的setState方法,重新绘制了控件。

    总结

    • 这个例子中,ParentWidget 父组建保存了变量_active的值;TapboxC组建保存了_highlight的值,然后_highlight根据_active和_highlight的不同值进行绘制。

    • 使用GestureDetector处理了点击事件

    • 学习了父子控件如何进行值传递

    相关文章

      网友评论

        本文标题:Flutter widget点击事件和点击态

        本文链接:https://www.haomeiwen.com/subject/uaywdqtx.html