美文网首页
basic.dart

basic.dart

作者: 小山包 | 来源:发表于2018-07-19 15:11 被阅读0次

    basic.dart

    [TOC]

    • basic.dart这个文件按对子节点的影响大致分成了6种Widget。
    • 按子节点的数量,可以分为SingleChildRenderObjectWidgetMultiChildRenderObjectWidget。也就是布局Widget与普通Widget的区别。相当于android中的ViewGroupView吧。

    PAINTING NODES

    对子节点施加额外的painting的效果,透明度、阴影、边角剪裁等。

    Opacity

    • 改变子节点的不透明度,效果图: opacity

      源码:

    import 'package:flutter/material.dart';
    
    class OpacityDemo extends StatefulWidget {
      @override
      _OpacityDemoState createState() {
        return _OpacityDemoState();
      }
    }
    
    class _OpacityDemoState extends State<OpacityDemo> {
      double _opacity = 0.0;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('OpacityDemo')),
          body: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Slider(
                value: _opacity,
                onChanged: (value) => setState(() => _opacity = value),
              ),
              Opacity(
                // 只有一个不透明度的参数,动态设置即可实现动画
                opacity: _opacity,
                child: Container(
                  width: 200.0,
                  height: 200.0,
                  color: Colors.red,
                ),
              ),
            ],
          ),
        );
      }
    }
    
    • Opacity的实现方式是先把子节点绘制到一个缓存中,然后把设置好的透明度与子节点混合(blend)。
    • 当不透明度为0和1的时候,效率会高一些,因为没了把子节点绘制到缓存中的步骤。
    • 跟动态添加或删除widget相比,设置不透明度(1或0)的效率要更高。
    • 如果要做不透明度的动画,使用AnimatedOpacity的效率要高很多,因为动态设置Opacity的不透明度会触发每一帧的刷新,而AnimatedOpacity不会。

    ShaderMask

    • 用shader给子节点增加一个mask。效果图: ShaderMas

      源码:

    import 'package:flutter/material.dart';
    
    class ShaderMaskDemo extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: ShaderMask(
            shaderCallback: (Rect bounds) {
              return RadialGradient(
                center: Alignment.topLeft,
                colors: <Color>[Colors.yellow, Colors.deepOrange.shade900],
                tileMode: TileMode.mirror,
              ).createShader(bounds);
            },
            child: Center(child: Text('I’m burning the memories')),
          ),
        );
      }
    }
    
    • RadialGradientcreateShader方法来自Gradient类,也就说只有Gradient的子类才能创建Shader
    • 这个Widget目前来看用的人还是比较少,github上相关的Issue也只有个位数。
    • 看了下Gradient是继承了Shader类的。

    BackdropFilter

    • 主要的一个应用是ios风格的毛玻璃效果。效果图: BackdropFilter

      源码:

    import 'package:flutter/material.dart';
    import 'dart:ui' as ui;
    
    class BackdropFilterDemo extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Stack(
            children: <Widget>[
              ConstrainedBox(
                  constraints: BoxConstraints.expand(), child: FlutterLogo()),
              BackdropFilter(
                filter: ui.ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
                child: Center(
                  child: Text(
                    'Frosted',
                    style: Theme.of(context).textTheme.display3,
                  ),
                ),
              ),
            ],
          ),
        );
      }
    }
    
    • BackdropFilter服务的对象应该是在它“后面”的那些Widget,而它的child只是借用了一下它的效果(让BackdropFilter以及child在“后面”的Widget基础之上产生毛玻璃效果)。
    • 最终产生毛玻璃效果的区域是child的区域。
    • 有一点搞不懂的是这里用的Text的毛玻璃的区域,为什么是不对称的?

    CustomPaint

    // TODO

    ClipRect

    • 把子节点的形状剪成矩形,不过一般的子节点都看不出来,因为大部分本身就是矩形的吧。效果图: ClipRect

      源码:

    import 'package:flutter/material.dart';
    
    class ClipRectDemo extends StatefulWidget {
      @override
      _ClipRectDemoState createState() {
        return _ClipRectDemoState();
      }
    }
    
    class _ClipRectDemoState extends State<ClipRectDemo> {
      double _heightFactor = 0.0;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('ClipRectDemo')),
          body: Column(
            children: <Widget>[
              Slider(
                value: _heightFactor,
                onChanged: (value) => setState(() => _heightFactor = value),
              ),
              ClipRect(
                // Align设置了heightFactor, 那么Align的高度为Container的_heightFactor倍
                // ClipRect之后, Container的下半部分就被剪掉了
                child: Align(
                  alignment: AlignmentDirectional.topCenter,
                  heightFactor: _heightFactor,
                  // Container的大小为整个body
                  child: Container(
                    height: 400.0,
                    color: Colors.red,
                  ),
                ),
              ),
            ],
          ),
        );
      }
    }
    
    • 默认情况ClipRect会禁止子节点超出它本身,但是可以通过自定义clipper属性来实现超出ClipRect的情况。clipper可以移动要剪的位置和大小,也就是那个Rect。自定义clipper单独发篇文章好了。

    ClipRRect

    • 作用和ClipRect一样,只不过有一个borderRadius参数,可以控制矩形的圆角,效果图: ClipRRect
      源码:
    import 'package:flutter/material.dart';
    
    class ClipRRectDemo extends StatefulWidget {
      @override
      _ClipRRectDemoState createState() {
        return _ClipRRectDemoState();
      }
    }
    
    class _ClipRRectDemoState extends State<ClipRRectDemo> {
      double _cornerRadius = 0.0;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('ClipRRectDemo')),
          body: Column(
            children: <Widget>[
              Slider(
                value: _cornerRadius,
                onChanged: (value) => setState(() => _cornerRadius = value),
              ),
              ClipRRect(
                // 控制圆角的角度
                borderRadius: BorderRadius.circular(_cornerRadius * 180),
                child: Container(
                  height: 400.0,
                  color: Colors.red,
                ),
              ),
            ],
          ),
        );
      }
    }
    

    ClipOval

    • ClipOval就是ClipRRect的圆角成90°的情况
      源码:
    import 'package:flutter/material.dart';
    
    class ClipOvalDemo extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('ClipOvalDemo')),
          body: ClipOval(
            child: Container(
              height: 400.0,
              color: Colors.red,
            ),
          ),
        );
      }
    }
    

    ClipPath

    • ClipPath默认的行为(clipper参数为空)与ClipRect一样,就是简单的矩形。那么也就可知Clip系列Widget就是ClipPath的特殊情况。
    • clipper放到proxy_box.dart再分析了。
      效果图: ClipPath
      源码:
    import 'package:flutter/material.dart';
    
    class ClipPathDemo extends StatefulWidget {
      @override
      _ClipPathDemoState createState() {
        return _ClipPathDemoState();
      }
    }
    
    class _ClipPathDemoState extends State<ClipPathDemo> {
      double _heightFactor = 0.0;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('ClipRectDemo')),
          body: Column(
            children: <Widget>[
              Slider(
                value: _heightFactor,
                onChanged: (value) => setState(() => _heightFactor = value),
              ),
              ClipPath(
                // Align设置了heightFactor, 那么Align的高度为Container的0.5倍
                // ClipRect之后, Container的下半部分就被剪掉了
                child: Align(
                  alignment: AlignmentDirectional.topCenter,
                  heightFactor: _heightFactor,
                  // Container的大小为整个body
                  child: Container(
                    height: 400.0,
                    color: Colors.red,
                  ),
                ),
              ),
            ],
          ),
        );
      }
    }
    

    PhysicalModel

    • PhysicalModel的一个主要作用就是给子节点添加阴影效果(由elevation指定),还可以指定阴影的颜色和子节点的形状,主要的功能就这几个。效果图: PhysicalModel
      源码:
    import 'package:flutter/material.dart';
    
    class PhysicalModelDemo extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('PhysicalModelDemo')),
          body: PhysicalModel(
            color: Colors.red,
            shape: BoxShape.circle,
            shadowColor: Colors.blueAccent,
            elevation: 20.0,
            child: Container(),
          ),
        );
      }
    }
    

    PhysicalShape

    • PhysicalShapePhysicalModel类似,只不过可以自定义path(即clipper参数)。

    POSITIONING AND SIZING NODES

    • 控制子节点的位置和大小

    Transform

    • 给子节点做一个变换,注意是静态的变换(也就是变换应用了之后再画出来),而不是动画!效果图: Transform

    源码:

    import 'package:flutter/material.dart';
    
    class TransformDemo extends StatefulWidget {
      @override
      TransformDemoState createState() {
        return TransformDemoState();
      }
    }
    
    class TransformDemoState extends State<TransformDemo> {
      double _angle = 0.0;
    
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Scaffold(
            appBar: AppBar(title: Text('TransformDemo')),
            body: Column(
              children: <Widget>[
                Slider(
                  value: _angle,
                  onChanged: (value) => setState(() => _angle = value),
                ),
                Transform.rotate(
                  alignment: AlignmentDirectional.center,
                  angle: _angle,
                  child: Center(
                    child: Container(
                      height: 200.0,
                      width: 200.0,
                      color: Colors.red,
                    ),
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    

    CompositedTransformTarget

    // TODO

    CompositedTransformFollower

    // TODO

    FittedBox

    • 提供了子节点在FittedBox中展示的几种策略,分别是fill(子节点长和宽都撑满父节点),contain(子节点包含在父节点中),cover(子节点覆盖住父节点所占的区域,但是不像fill那样拉伸,而是通过剪裁然后放大的方式实现覆盖),fitHeight(按子节点的高度撑满父节点,宽度不管它),fitWidth(按子节点的宽度撑满父节点,高度不管它),none(按原图显示),scaleDown(如果图片需要缩小的话,那么就跟contain效果一样,其他情况和none效果一样)。效果图: FittedBox
      源码:
    import 'package:flutter/material.dart';
    
    class FittedBoxDemo extends StatefulWidget {
      @override
      FittedBoxDemoState createState() {
        return FittedBoxDemoState();
      }
    }
    
    class FittedBoxDemoState extends State<FittedBoxDemo> {
      BoxFit _fit = BoxFit.cover;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('FittedBoxDemo')),
          body: Column(
            children: <Widget>[
              Row(
                children: <Widget>[
                  RaisedButton(
                    onPressed: () {
                      setState(() => _fit = BoxFit.fill);
                    },
                    child: Text('fill'),
                  ),
                  RaisedButton(
                    onPressed: () {
                      setState(() => _fit = BoxFit.contain);
                    },
                    child: Text('contain'),
                  ),
                  RaisedButton(
                    onPressed: () {
                      setState(() => _fit = BoxFit.cover);
                    },
                    child: Text('cover'),
                  ),
                  RaisedButton(
                    onPressed: () {
                      setState(() => _fit = BoxFit.fitWidth);
                    },
                    child: Text('fitWidth'),
                  ),
                ],
              ),
              Row(
                children: <Widget>[
                  RaisedButton(
                    onPressed: () {
                      setState(() => _fit = BoxFit.fitHeight);
                    },
                    child: Text('fitHeight'),
                  ),
                  RaisedButton(
                    onPressed: () {
                      setState(() => _fit = BoxFit.none);
                    },
                    child: Text('none'),
                  ),
                  RaisedButton(
                    onPressed: () {
                      setState(() => _fit = BoxFit.scaleDown);
                    },
                    child: Text('scaleDown'),
                  ),
                ],
              ),
              Center(
                child: Container(
                  height: 200.0,
                  width: 200.0,
                  color: Colors.red,
                  child: FittedBox(
                    fit: _fit,
                    child: Image.asset('assets/rabbit.png'),
                  ),
                ),
              ),
            ],
          ),
        );
      }
    }
    

    FractionalTranslation

    • 依据子节点自身的百分比来对子节点做出变换。效果图: FractionalTranslation

      源码:

    import 'package:flutter/material.dart';
    
    class FractionalTranslationDemo extends StatefulWidget {
      @override
      FractionalTranslationDemoState createState() {
        return FractionalTranslationDemoState();
      }
    }
    
    class FractionalTranslationDemoState extends State<FractionalTranslationDemo> {
      double _offset = 0.0;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('FractionalTranslationDemo')),
          body: Column(
            children: <Widget>[
              Slider(
                value: _offset,
                onChanged: (value) => setState(() => _offset = value),
              ),
              Container(
                color: Colors.blueAccent,
                child: GestureDetector(
                  onTap: () => print('tapped!!!!'),
                  child: FractionalTranslation(
                    transformHitTests: true,
                    translation: Offset(_offset, _offset),
                    child: Container(
                      height: 200.0,
                      width: 200.0,
                      color: Colors.red,
                    ),
                  ),
                ),
              ),
            ],
          ),
        );
      }
    }
    
    • 有一点需要注意的是transformHitTests参数,这个参数表示接收hit test的区域是否也跟着Transition一起走。

    RotatedBox

    • 以90°为单位对子节点进行旋转。效果图: RotatedBox

      源码:

    import 'package:flutter/material.dart';
    
    class RotatedBoxDemo extends StatefulWidget {
      @override
      RotatedBoxDemoState createState() {
        return new RotatedBoxDemoState();
      }
    }
    
    class RotatedBoxDemoState extends State<RotatedBoxDemo> {
      int turns = 0;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('RotatedBoxDemo')),
          body: GestureDetector(
            onTap: () {
              setState(() => ++turns);
            },
            child: RotatedBox(
              quarterTurns: turns,
              child: Center(
                child: Image.asset('assets/rabbit.png'),
              ),
            ),
          ),
        );
      }
    }
    
    • quarterTurns可以一直累加,它自己会做判断。

    Padding

    • 给子节点增加(其实是外边距吧)padding。效果图: Padding

      源码:

    import 'package:flutter/material.dart';
    
    class PaddingDemo extends StatefulWidget {
      @override
      PaddingDemoState createState() {
        return new PaddingDemoState();
      }
    }
    
    class PaddingDemoState extends State<PaddingDemo> {
      double _insets = 0.0;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('PaddingDemo')),
          body: Column(
            children: <Widget>[
              Slider(
                value: _insets,
                onChanged: (value) => setState(() => _insets = value),
              ),
              Container(
                color: Colors.blueAccent,
                child: Center(
                  child: Padding(
                    padding: EdgeInsets.all(_insets * 50.0),
                    child: Container(
                      width: 200.0,
                      height: 200.0,
                      color: Colors.red,
                    ),
                  ),
                ),
              ),
            ],
          ),
        );
      }
    }
    
    • 关于直接使用Padding和使用Containerpadding属性来构造padding,实际上如果Container只设置了padding属性的话,那么构造出来的就是单纯的PaddingContainer只是一个便利的控件而已。

    Align

    • 对子节点进行对齐的控件。效果图: Align

      源码:

    import 'package:flutter/material.dart';
    
    class AlignDemo extends StatefulWidget {
      @override
      AlignDemoState createState() {
        return new AlignDemoState();
      }
    }
    
    class AlignDemoState extends State<AlignDemo> {
      AlignmentDirectional _directional = AlignmentDirectional.center;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('AlignDemo')),
          body: Column(
            children: <Widget>[
              GridView.count(
                crossAxisCount: 3,
                shrinkWrap: true,
                childAspectRatio: 3.0,
                crossAxisSpacing: 8.0,
                mainAxisSpacing: 8.0,
                children: <Widget>[
                  RaisedButton(
                    onPressed: () {
                      setState(() {
                        _directional = AlignmentDirectional.topStart;
                      });
                    },
                    child: Text('topStart'),
                  ),
                  RaisedButton(
                    onPressed: () {
                      setState(() {
                        _directional = AlignmentDirectional.topCenter;
                      });
                    },
                    child: Text('topCenter'),
                  ),
                  RaisedButton(
                    onPressed: () {
                      setState(() {
                        _directional = AlignmentDirectional.topEnd;
                      });
                    },
                    child: Text('topEnd'),
                  ),
                  RaisedButton(
                    onPressed: () {
                      setState(() {
                        _directional = AlignmentDirectional.centerStart;
                      });
                    },
                    child: Text('centerStart'),
                  ),
                  RaisedButton(
                    onPressed: () {
                      setState(() {
                        _directional = AlignmentDirectional.center;
                      });
                    },
                    child: Text('center'),
                  ),
                  RaisedButton(
                    onPressed: () {
                      setState(() {
                        _directional = AlignmentDirectional.centerEnd;
                      });
                    },
                    child: Text('centerEnd'),
                  ),
                  RaisedButton(
                    onPressed: () {
                      setState(() {
                        _directional = AlignmentDirectional.bottomStart;
                      });
                    },
                    child: Text('bottomStart'),
                  ),
                  RaisedButton(
                    onPressed: () {
                      setState(() {
                        _directional = AlignmentDirectional.bottomCenter;
                      });
                    },
                    child: Text('bottomCenter'),
                  ),
                  RaisedButton(
                    onPressed: () {
                      setState(() {
                        _directional = AlignmentDirectional.bottomEnd;
                      });
                    },
                    child: Text('bottomEnd'),
                  ),
                ],
              ),
              Expanded(
                child: Center(
                  child: Align(
                    alignment: _directional,
                    child: Text(
                      'i am text',
                      style: Theme.of(context).textTheme.headline,
                    ),
                  ),
                ),
              ),
            ],
          ),
        );
      }
    }
    
    • Align有个widthFactorheightFactor,它们的作用是确定Align本身的大小,Align的大小(如果设置了*Factor)会是子节点的宽/高*factor,比如说如果子节点宽100,widthFactor为2.0的话,那么Align自身的宽度就为200.0,高度同理。
    • 如果factor没有设置,且有约束(?什么意思)的话,那么Align会尽可能的大
    • 如果没有约束,且factor为null的话,那么Align就是子节点的大小。

    Center

    • Center没什么好讲的,算是最常用的几种Widget之一了,就是Align的一个特殊情况/别名,它本身也是继承了Align类,它的widthFactorheightFactorAlign的一样。效果图: Center
      源码:
    import 'package:flutter/material.dart';
    
    class CenterDemo extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('CenterDemo')),
          body: Center(
            child: Text('i am in center'),
          ),
        );
      }
    }
    

    CustomSingleChildLayout

    • [SingleChildLayoutDelegate]没有对外开放的已实现的实现类, flutter内建的实现类(但是是private的)的有(包括但不限于): _ToolbarContainerLayout(这个appbar内部使用的)。也就是说要用[CustomSingleChildLayout]的话, 就需要自己去实现[SingleChildLayoutDelegate]这里暂时就不去搞了。

    LayoutId

    // TODO

    CustomMultiChildLayout

    // TODO

    SizedBox

    • 强制子节点拥有SizedBox指定的大小。效果图: SizedBox
      源码:
    import 'package:flutter/material.dart';
    
    class SizedBoxDemo extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('SizedBoxDemo')),
          body: Center(
            child: SizedBox(
              width: 200.0,
              height: 200.0,
              child: Container(
                color: Colors.red,
              ),
            ),
          ),
        );
      }
    }
    
    • SizedBox有个expand命名构造函数,调用这个构造函数的时候,会生成一个撑满父节点的SizedBox

    ConstrainedBox

    • 对子节点施加额外的约束,但是所谓的最大(小)宽(高)度,到底是以什么策略进行变换还是搞不清楚。之后涉及到BoxConstraint的时候再来细看吧。效果图: ConstrainedBox
      源码:
    import 'package:flutter/material.dart';
    
    class ConstrainedBoxDemo extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('ConstrainedBoxDemo')),
          body: Column(
            children: <Widget>[
              Flexible(
                child: Container(
                  color: Colors.blueAccent,
                ),
              ),
              ConstrainedBox(
                constraints: BoxConstraints(minHeight: 100.0, maxHeight: 200.0),
                child: Container(
                  color: Colors.red,
                ),
              ),
            ],
          ),
        );
      }
    }
    

    UnconstrainedBox

    // TODO

    FractionallySizedBox

    • 对子节点施加一个百分比,这个百分比是FractionallySizedBox的可用空间的百分比。比较适合那种一个按钮占据一行的场景,可以设置按钮以屏幕宽为基准进行百分比缩小,这样的话在不同尺寸的设备上适应性会比较好。效果图: FractionallySizedBox
      源码:
    import 'package:flutter/material.dart';
    
    class FractionallySizedBoxDemo extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('FractionallySizedBoxDemo')),
          body: Container(
            color: Colors.blueAccent,
            constraints: BoxConstraints.expand(),
            child: Column(
              children: <Widget>[
                FractionallySizedBox(
                  widthFactor: 0.5,
                  child: RaisedButton(
                    onPressed: () {},
                    child: Text('child1'),
                  ),
                ),
                SizedBox(height: 8.0),
                FractionallySizedBox(
                  widthFactor: 0.8,
                  child: RaisedButton(
                    onPressed: () {},
                    child: Text('child2'),
                  ),
                ),
                SizedBox(height: 8.0),
                FractionallySizedBox(
                  widthFactor: 0.6,
                  child: RaisedButton(
                    onPressed: () {},
                    child: Text('child2'),
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    

    LimitedBox

    // TODO

    OverflowBox

    // TODO

    SizedOverflowBox

    // TODO

    Offstage

    // TODO

    _OffstageElement

    // TODO

    AspectRatio

    // TODO

    IntrinsicWidth

    // TODO

    IntrinsicHeight

    // TODO

    Baseline

    // TODO

    SLIVERS

    SliverToBoxAdapter

    // TODO

    SliverPadding

    // TODO

    LAYOUT NODES

    ListBody

    // TODO

    Stack

    // TODO

    IndexedStack

    // TODO

    Positioned

    // TODO

    PositionedDirectional

    // TODO

    Flex

    // TODO

    Row

    // TODO

    Column

    // TODO

    Flexible

    // TODO

    Expanded

    // TODO

    Wrap

    // TODO

    Flow

    // TODO

    RichText

    // TODO

    RawImage

    // TODO

    DefaultAssetBundle

    // TODO

    WidgetToRenderBoxAdapter

    // TODO

    EVENT HANDLING

    Listener

    // TODO

    RepaintBoundary

    // TODO

    IgnorePointer

    • 此节点以及其子节点都将忽略点击事件,用ignoring参数区分是否忽略。效果图: IgnorePointer
      源码:
    import 'package:flutter/material.dart';
    
    class IgnorePointerDemo extends StatefulWidget {
      @override
      _IgnorePointerDemoState createState() {
        return _IgnorePointerDemoState();
      }
    }
    
    class _IgnorePointerDemoState extends State<IgnorePointerDemo> {
      bool _ignore = true;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('IgnorePointerDemo')),
          body: Container(
            color: Colors.red,
            alignment: AlignmentDirectional.center,
            child: Column(
              children: <Widget>[
                Switch(
                  value: _ignore,
                  onChanged: (value) {
                    setState(() => _ignore = value);
                  },
                ),
                IgnorePointer(
                  ignoring: _ignore,
                  child: RaisedButton(
                    onPressed: () => print('clicked!!'),
                    child: Text('ignore'),
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    
    • switch开关控制了是否忽略点击事件。

    AbsorbPointer

    • 这个控件会absorb(吸收)掉点击事件,跟其他框架里的swallow(吞)是一个意思吧。这个控件和上个控件的区别在于,这个控件本身是能够响应点击事件的,它做的是阻止事件传播到它的子节点上去,而IgnorePointer本身也不再接收事件了。效果图: AbsorbPointer
      源码:
    import 'package:flutter/material.dart';
    
    class AbsorbPointerDemo extends StatefulWidget {
      @override
      _AbsorbPointerDemo createState() {
        return _AbsorbPointerDemo();
      }
    }
    
    class _AbsorbPointerDemo extends State<AbsorbPointerDemo> {
      bool _absorb = true;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('AbsorbPointerDemo')),
          body: Container(
            color: Colors.red,
            alignment: AlignmentDirectional.center,
            child: Column(
              children: <Widget>[
                Switch(
                  value: _absorb,
                  onChanged: (value) {
                    setState(() => _absorb = value);
                  },
                ),
                GestureDetector(
                  onTap: () => print('tap in GestureDetector'),
                  child: AbsorbPointer(
                    absorbing: _absorb,
                    child: RaisedButton(
                      onPressed: () => print('tap in RaisedButton'),
                      child: Text('absorb'),
                    ),
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    
    • GestureDetector的响应反映AbsorbPointer本身是可以接收事件的。

    MetaData

    // TODO

    UTILITY NODES

    Semantics

    // TODO

    MergeSemantics

    // TODO

    BlockSemantics

    // TODO

    ExcludeSemantics

    // TODO

    KeyedSubtree

    // TODO

    Builder

    // TODO

    StatefulBuilder

    // TOD

    相关文章

      网友评论

          本文标题:basic.dart

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