basic.dart

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容