# node

name: SliverPersistentHeader基本使用
subtitle:
  【delegate】 : 代理   【SliverPersistentHeaderDelegate】
  【floating】 : 是否浮动   【bool】
  【pinned】 : 是否顶部停留   【bool】

code:
  class SliverPersistentHeaderDemo extends StatelessWidget {
    final data = <Color>[
      Colors.purple[50],
      Colors.purple[100],
      Colors.purple[200],
      Colors.purple[300],
      Colors.purple[400],
      Colors.purple[500],
      Colors.purple[600],
      Colors.purple[700],
      Colors.purple[800],
      Colors.purple[900],
    ];

    @override
    Widget build(BuildContext context) {
      return Container(
        height: 500,
        child: CustomScrollView(
          slivers: <Widget>[
            _buildSliverAppBar(),
            _buildPersistentHeader('袅缈岁月，青丝银发',Color(0xffe7fcc9)),
            _buildCommonWidget(),
            _buildPersistentHeader('以梦为马，不负韶华',Color(0xffcca4ff)),
            _buildSliverList()
          ],
        ),
      );
    }

    Widget _buildCommonWidget() => SliverToBoxAdapter(
      child: Container(
        padding: EdgeInsets.symmetric(horizontal: 10),
        color: Colors.grey.withAlpha(22),
        child: ListTile(
          leading: Image.asset("assets/images/icon_head.png"),
          title: Text("以梦为马"),
          subtitle: Text("海子"),
          selected: true,
          contentPadding: EdgeInsets.all(5),
          trailing: Icon(Icons.more_vert),
        ),
      ),
    );
    Widget _buildPersistentHeader(String text,Color color) => SliverPersistentHeader(
      pinned: true,
      delegate: _SliverDelegate(
          minHeight: 40.0,
          maxHeight: 100.0,
          child: Container(
            color: color,
            child: Center(
              child: Text(text, style: TextStyle(
                  fontSize: 18,
                  shadows: [Shadow(color: Colors.white, offset: Offset(1, 1))]),
            ),
          )),
    ));

    Widget _buildSliverList() => SliverList(
      delegate: SliverChildBuilderDelegate(
              (_, int index) => Container(
            alignment: Alignment.center,
            width: 100,
            height: 60,
            color: data[index],
            child: Text(
              colorString(data[index]),
              style: TextStyle(color: Colors.white, shadows: [
                Shadow(
                    color: Colors.black,
                    offset: Offset(.5, .5),
                    blurRadius: 2)
              ]),
            ),
          ),
          childCount: data.length),
    );

    Widget _buildSliverAppBar() {
      return SliverAppBar(
        expandedHeight: 190.0,
        leading: _buildLeading(),
        title: Text('张风捷特烈'),
        actions: _buildActions(),
        elevation: 2,
        pinned: true,
        backgroundColor: Colors.orange,
        flexibleSpace: FlexibleSpaceBar(
          //伸展处布局
          titlePadding: EdgeInsets.only(left: 55, bottom: 15), //标题边距
          collapseMode: CollapseMode.parallax, //视差效果
          background: Image.asset(
            "assets/images/caver.jpeg",
            fit: BoxFit.cover,
          ),
        ),
      );
    }

    Widget _buildLeading() => Container(
        margin: EdgeInsets.all(10),
        child: Image.asset('assets/images/icon_head.png'));

    List<Widget> _buildActions() => <Widget>[
      IconButton(
        onPressed: () {},
        icon: Icon(
          Icons.star_border,
          color: Colors.white,
        ),
      )
    ];

    String colorString(Color color) =>
        "#${color.value.toRadixString(16).padLeft(8, '0').toUpperCase()}";
  }


  class _SliverDelegate extends SliverPersistentHeaderDelegate {
    _SliverDelegate({
      @required this.minHeight,
      @required this.maxHeight,
      @required this.child,
    });

    final double minHeight; //最小高度
    final double maxHeight; //最大高度
    final Widget child; //孩子

    @override
    double get minExtent => minHeight;

    @override
    double get maxExtent => max(maxHeight, minHeight);

    @override
    Widget build(
        BuildContext context, double shrinkOffset, bool overlapsContent) {
      return new SizedBox.expand(child: child);
    }

    @override //是否需要重建
    bool shouldRebuild(_SliverDelegate oldDelegate) {
      return maxHeight != oldDelegate.maxHeight ||
          minHeight != oldDelegate.minHeight ||
          child != oldDelegate.child;
    }
  }


name: SliverPadding基本使用
subtitle:
  【sliver】 : 子组件 【Widget】
  【padding】 : 内边距 【EdgeInsetsGeometry】

code:
  class SliverPaddingDemo extends StatelessWidget {
    final data = List.generate(128, (i) => Color(0xFF6600FF - 2 * i));

    @override
    Widget build(BuildContext context) {
      return Container(
        height: 300,
        child: CustomScrollView(
          slivers: <Widget>[_buildSliverAppBar(), SliverPadding(
              padding: EdgeInsets.only(top: 10),
              sliver
              : _buildSliverGrid())],
        ),
      );
    }

    Widget _buildSliverGrid() => SliverGrid.extent(
      childAspectRatio: 1 / 0.618,
      maxCrossAxisExtent: 180,
      crossAxisSpacing: 5,
      mainAxisSpacing: 5,
      children: data
          .map((e) => Container(
        alignment: Alignment.center,
        width: 100,
        height: 60,
        color: e,
        child: Text(
          colorString(e),
          style: TextStyle(color: Colors.white, shadows: [
            Shadow(
                color: Colors.black,
                offset: Offset(.5, .5),
                blurRadius: 2)
          ]),
        ),
      ))
          .toList(),
    );

    Widget _buildSliverAppBar() {
      return SliverAppBar(
        expandedHeight: 190.0,
        leading: _buildLeading(),
        title: Text('张风捷特烈'),
        actions: _buildActions(),
        elevation: 5,
        pinned: true,
        backgroundColor: Colors.orange,
        flexibleSpace: FlexibleSpaceBar(
          //伸展处布局
          titlePadding: EdgeInsets.only(left: 55, bottom: 15), //标题边距
          collapseMode: CollapseMode.parallax, //视差效果
          background: Image.asset(
            "assets/images/caver.jpeg",
            fit: BoxFit.cover,
          ),
        ),
      );
    }

    Widget _buildLeading() => Container(
        margin: EdgeInsets.all(10),
        child: Image.asset('assets/images/icon_head.png'));

    List<Widget> _buildActions() => <Widget>[
      IconButton(
        onPressed: () {},
        icon: Icon(
          Icons.star_border,
          color: Colors.white,
        ),
      )
    ];

    String colorString(Color color) =>
        "#${color.value.toRadixString(16).padLeft(8, '0').toUpperCase()}";
  }


name: SliverOpacity基本使用
subtitle:
  【opacity】 : 透明度 【double】
  【sliver】 : 子组件 【Widget】

code:
  class SliverOpacityDemo extends StatelessWidget {
    final data = List.generate(128, (i) => Color(0xFF6600FF - 2 * i));

    @override
    Widget build(BuildContext context) {
      return Container(
        height: 300,
        child: CustomScrollView(
          slivers: <Widget>[
            _buildSliverAppBar(),
            SliverPadding(
                padding: EdgeInsets.only(top: 10),
                sliver: SliverOpacity(opacity: 0.2, sliver: _buildSliverGrid()))
          ],
        ),
      );
    }

    Widget _buildSliverGrid() => SliverGrid.extent(
          childAspectRatio: 1 / 0.618,
          maxCrossAxisExtent: 180,
          crossAxisSpacing: 5,
          mainAxisSpacing: 5,
          children: data
              .map((e) => Container(
                    alignment: Alignment.center,
                    width: 100,
                    height: 60,
                    color: e,
                    child: Text(
                      colorString(e),
                      style: TextStyle(color: Colors.white, shadows: [
                        Shadow(
                            color: Colors.black,
                            offset: Offset(.5, .5),
                            blurRadius: 2)
                      ]),
                    ),
                  ))
              .toList(),
        );

    Widget _buildSliverAppBar() {
      return SliverAppBar(
        expandedHeight: 190.0,
        leading: _buildLeading(),
        title: Text('张风捷特烈'),
        actions: _buildActions(),
        elevation: 5,
        pinned: true,
        backgroundColor: Colors.orange,
        flexibleSpace: FlexibleSpaceBar(
          //伸展处布局
          titlePadding: EdgeInsets.only(left: 55, bottom: 15), //标题边距
          collapseMode: CollapseMode.parallax, //视差效果
          background: Image.asset(
            "assets/images/caver.jpeg",
            fit: BoxFit.cover,
          ),
        ),
      );
    }

    Widget _buildLeading() => Container(
        margin: EdgeInsets.all(10),
        child: Image.asset('assets/images/icon_head.png'));

    List<Widget> _buildActions() => <Widget>[
          IconButton(
            onPressed: () {},
            icon: Icon(
              Icons.star_border,
              color: Colors.white,
            ),
          )
        ];

    String colorString(Color color) =>
        "#${color.value.toRadixString(16).padLeft(8, '0').toUpperCase()}";
  }


name: AboutListTile基本使用
subtitle:
  【icon】 : 左图标   【Widget】
  【applicationIcon】 : 左上图标   【Widget】
  【applicationVersion】 : 版本号  【String】
  【applicationName】 : 应用名  【String】
  【applicationLegalese】 : 应用律术   【String】
  【aboutBoxChildren】 : 弹框内容组件   【List<Widget>】

code:
  class AboutListTileDemo extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return AboutListTile(
        icon: Icon(Icons.info),
        applicationIcon: FlutterLogo(),
        applicationName: 'Flutter Unit',
        applicationVersion: 'v0.0.1',
        applicationLegalese: 'Copyright© 2018-2020 张风捷特烈',
        aboutBoxChildren: [
          Padding(
            padding: const EdgeInsets.all(10.0),
            child: Text(
              '      FlutterUnit是【张风捷特烈】的开源项目，'
              '收录Flutter的200+组件，并附加详细介绍以及操作交互，'
              '希望帮助广大编程爱好者入门Flutter。'
              '更多知识可以关注掘金账号、公众号【编程之王】。',
              style: TextStyle(color: Color(0xff999999), fontSize: 16),
              textAlign: TextAlign.justify,
            ),
          ),
        ],
      );
    }
  }


name: Scrollbar基本使用
subtitle:
  【child】 : 子组件 【Widget】
  【controller】 : 控制器 【ScrollController】

code:
  class CustomScrollbar extends StatelessWidget {
    final data = <Color>[
      Colors.purple[50],
      Colors.purple[100],
      Colors.purple[200],
      Colors.purple[300],
      Colors.purple[400],
      Colors.purple[500],
      Colors.purple[600],
      Colors.purple[700],
      Colors.purple[800],
      Colors.purple[900],
    ];

    @override
    Widget build(BuildContext context) {
      return Container(
        height: 200,
        child: Scrollbar(
          child: ListView(
            padding: EdgeInsets.symmetric(horizontal: 5),
            children: data
                .map((color) => Container(
              alignment: Alignment.center,
              width: 100,
              height: 50,
              color: color,
              child: Text(
                colorString(color),
                style: TextStyle(color: Colors.white, shadows: [
                  Shadow(
                      color: Colors.black,
                      offset: Offset(.5, .5),
                      blurRadius: 2)
                ]),
              ),
            ))
                .toList(),
          ),
        ),
      );
    }

    String colorString(Color color) =>
        "#${color.value.toRadixString(16).padLeft(8, '0').toUpperCase()}";
  }


name: CupertinoScrollbar基本使用
subtitle:
  【child】 : 子组件 【Widget】
  【controller】 : 控制器 【ScrollController】

code:
  class CustomCupertinoScrollbar extends StatelessWidget {
    final data = <Color>[
      Colors.purple[50],
      Colors.purple[100],
      Colors.purple[200],
      Colors.purple[300],
      Colors.purple[400],
      Colors.purple[500],
      Colors.purple[600],
      Colors.purple[700],
      Colors.purple[800],
      Colors.purple[900],
    ];
    
    @override
    Widget build(BuildContext context) {
      return Container(
        height: 200,
        child: CupertinoScrollbar(
          child: ListView(
            padding: EdgeInsets.symmetric(horizontal: 5),
            children: data
                .map((color) => Container(
              alignment: Alignment.center,
              width: 100,
              height: 50,
              color: color,
              child: Text(
                colorString(color),
                style: TextStyle(color: Colors.white, shadows: [
                  Shadow(
                      color: Colors.black,
                      offset: Offset(.5, .5),
                      blurRadius: 2)
                ]),
              ),
            ))
                .toList(),
          ),
        ),
      );
    }

    String colorString(Color color) =>
        "#${color.value.toRadixString(16).padLeft(8, '0').toUpperCase()}";
  }


name: SliverAppBar基本使用
subtitle:
  【title】 : 标题组件   【Widget】
  【titlePadding】 : 标题间距   【EdgeInsetsGeometry】
  【collapseMode】 : 折叠模式   【CollapseMode】
  【stretchModes】 : 延伸模式   【List<StretchMode>】
  【background】 : 背景组件   【Widget】
  【centerTitle】 : 是否居中   【bool】

code:
  class FlexibleSpaceBarDemo extends StatelessWidget {

    final data = <Color>[
      Colors.blue[50],
      Colors.blue[100],
      Colors.blue[200],
      Colors.blue[300],
      Colors.blue[400],
      Colors.blue[500],
      Colors.blue[600],
      Colors.blue[700],
      Colors.blue[800],
      Colors.blue[900],
    ];

    @override
    Widget build(BuildContext context) {
      return
          Container(
            height: 300,
            child: CustomScrollView(
              slivers: <Widget>[
                _buildSliverAppBar(),
                _buildSliverFixedExtentList()
              ],
            ),
      );
    }

    Widget _buildSliverAppBar() {
      return SliverAppBar(
        expandedHeight: 190.0,
        leading: _buildLeading(),
        actions: _buildActions(),
        pinned: true,
        backgroundColor: Colors.blue,
        flexibleSpace: FlexibleSpaceBar(//伸展处布局
          centerTitle: false,
          title: Text('张风捷特烈',style: TextStyle(shadows: [
            Shadow(color: Colors.blue, offset: Offset(1, 1), blurRadius: 2)
          ]),),
          titlePadding: EdgeInsets.only(left: 55, bottom: 15), //标题边距
          collapseMode: CollapseMode.parallax, //视差效果
          stretchModes: [StretchMode.blurBackground,StretchMode.zoomBackground],
          background: Image.asset(
            "assets/images/caver.jpeg",
            fit: BoxFit.cover,
          ),
        ),
      );
    }

    Widget _buildLeading() => Container(
        margin: EdgeInsets.all(10),
        child: Image.asset('assets/images/icon_head.png'));

    List<Widget> _buildActions() => <Widget>[
      IconButton(
        onPressed: () {},
        icon: Icon(
          Icons.star_border,
          color: Colors.white,
        ),
      )
    ];

    Widget _buildSliverFixedExtentList() => SliverFixedExtentList(
      itemExtent: 60,
      delegate: SliverChildBuilderDelegate(
              (_, int index) => Container(
            alignment: Alignment.center,
            width: 100,
            height: 50,
            color: data[index],
            child: Text(
              colorString(data[index]),
              style: TextStyle(color: Colors.white, shadows: [
                Shadow(
                    color: Colors.black,
                    offset: Offset(.5, .5),
                    blurRadius: 2)
              ]),
            ),
          ),
          childCount: data.length),
    );

    String colorString(Color color) =>
        "#${color.value.toRadixString(16).padLeft(8, '0').toUpperCase()}";
  }


name: ErrorWidget基本使用
subtitle: 入参 : 显示信息 【Object】
code:
  class ErrorWidgetDemo extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return Container(
        height: 200,
        child: ErrorWidget(
            'I am Error ErrorWidget
  '
                'But now, there has no error.'
        ),
      );
    }
  }


name: Form基本使用
subtitle:
  【child】 : 子组件   【Widget】
  【onChanged】 : 表单变化回调   【VoidCallback】
  【onWillPop】 : 返回回调  【WillPopCallback】

code:
  class CustomForm extends StatefulWidget {
    @override
    _CustomFormState createState() => _CustomFormState();
  }

  class _CustomFormState extends State<CustomForm> {
    GlobalKey<FormState> _formKey = GlobalKey<FormState>();

    @override
    Widget build(BuildContext context) {
      return Container(
        child: Form(
          onWillPop: () => _willPop(context),
          key: _formKey,
          onChanged: () {
            print('Form---onChanged');
          },
          child:
              Stack(
                alignment: Alignment.centerRight,
                children: <Widget>[
                  Container(
                    width: 350,
                    child: UnconstrainedBox(
                      child: Container(
                        width: 200,
                        height: 70,
                        child: TextFormField(
                          style: TextStyle(textBaseline: TextBaseline.alphabetic),
                          decoration: InputDecoration(
                            border: OutlineInputBorder(),
                            labelText: 'username',
                          ),
                          validator: _validateUsername,
                        ),
                      ),
                    ),
                  ),
                  Positioned(
                      top: 0, right: 0, child: _buildSubmitButton(context)),
                ],
          ),
        ),
      );
    }

    String _validateUsername(value) {
      if (value.isEmpty) {
        return '用户名不能为空';
      }
      return null;
    }

    RaisedButton _buildSubmitButton(BuildContext context) {
      return RaisedButton(
        color: Colors.blue,
        shape: CircleBorder(
          side: BorderSide(width: 2.0, color: Color(0xFFFFDFDFDF)),
        ),
        onPressed: _onSubmit,
        child: Icon(
          Icons.check,
          color: Colors.white,
        ),
      );
    }

    _onSubmit(){
      if (_formKey.currentState.validate()) {
        Navigator.of(context).pop();
      }
    }

    Future<bool> _willPop(context) async {
      return await showDialog(
            context: context,
            builder: (context) => AlertDialog(
              shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.all(Radius.circular(10))),
              title: Text('提示'),
              content: Text('你确定要离开此页吗?'),
              actions: <Widget>[
                FlatButton(
                  onPressed: () => Navigator.of(context).pop(true),
                  child: Text('确定'),
                ),
                FlatButton(
                  onPressed: () => Navigator.of(context).pop(false),
                  child: Text('取消'),
                ),
              ],
            ),
          ) ??
          false;
    }
  }


name: TextFormField基本使用
subtitle:
      基本属性和TextField一致，详见之
  【validator】 : 验证函数   【FormFieldValidator<String> 】
  【onFieldSubmitted】 : 提交回调   【ValueChanged<String>】
  【onSaved】 : 表单save时回调  【FormFieldSetter<String>】

code:
  class CustomTextFormField extends StatefulWidget {
    @override
    _CustomTextFormFieldState createState() => _CustomTextFormFieldState();
  }

  class _CustomTextFormFieldState extends State<CustomTextFormField> {
    GlobalKey<FormState> _formKey = GlobalKey<FormState>();

    @override
    Widget build(BuildContext context) {
      return Container(
        child: Form(
          key: _formKey,
          child:
          Stack(
            alignment: Alignment.centerRight,
            children: <Widget>[
              Container(
                width: 350,
                child: UnconstrainedBox(
                  child: Container(
                    width: 200,
                    height: 70,
                    child: TextFormField(
                      style: TextStyle(textBaseline: TextBaseline.alphabetic),
                      decoration: InputDecoration(
                        border: OutlineInputBorder(),
                        labelText: 'username',
                      ),
                      validator: _validateUsername,
                      onFieldSubmitted: _onFieldSubmitted,
                      onSaved: _onSaved,
                    ),
                  ),
                ),
              ),
              Positioned(
                  top: 0, right: 0, child: _buildSubmitButton(context)),
            ],
          ),
        ),
      );
    }

    String _validateUsername(value) {
      if (value.isEmpty) {
        return '用户名不能为空';
      }
      return null;
    }
    _onSaved(value){
      print('onSaved:'+value);
    }

    void _onFieldSubmitted(value) {
      print('onFieldSubmitted:'+value);
    }

    RaisedButton _buildSubmitButton(BuildContext context) {
      return RaisedButton(
        color: Colors.blue,
        shape: CircleBorder(
          side: BorderSide(width: 2.0, color: Color(0xFFFFDFDFDF)),
        ),
        onPressed: _onSubmit,
        child: Icon(
          Icons.check,
          color: Colors.white,
        ),
      );
    }

    _onSubmit(){
      _formKey.currentState.save();
      if (_formKey.currentState.validate()) {
        FocusScope.of(context).requestFocus(FocusNode());
      }
    }
  }


name: Stepper基本使用
subtitle:
  【steps】 : 步骤列表   【List<Step>】
  【currentStep】 : 当前步骤   【double】
  【onStepTapped】 : 点击回调   【ValueChanged<int>】
  【onStepCancel】 : 上一步回调  【VoidCallback】
  【controlsBuilder】 : 控制器构造  【ControlsWidgetBuilder】

code:
  class StepperDemo extends StatefulWidget {
    @override
    _StepperDemoState createState() => _StepperDemoState();
  }

  class _StepperDemoState extends State<StepperDemo> {
    int _position = 0;

    final stepsData = {
      "填写表单":'请按表单填写个人信息。',
      "邮箱校验":'已将邮件发送至您的邮箱，请按照相关指示对您的账号进行邮箱校验。',
      "注册完成":'恭喜您，注册完成！',
    };

    final steps = [
      Step(
        title: Text("填写表单"),
        content: Container(height: 60, child: Text("请按表单填写个人信息")),
      ),
      Step(title: Text("邮箱校验"), content: Text("请对您的账号进行邮箱校验")),
      Step(title: Text("注册完成"), content: Text("恭喜您，注册完成")),
    ];

    @override
    Widget build(BuildContext context) {
      return Container(
        height: 200,
        child: Stepper(
            type:StepperType.horizontal,
            currentStep: _position,
            onStepTapped: (index) {
              setState(() {
                _position = index;
              });
            },
            onStepContinue: () {
              setState(() {
                if (_position < 2) {
                  _position++;
                }
              });
            },
            onStepCancel: () {
              if (_position > 0) {
                setState(() {
                  _position--;
                });
              }
            },
            controlsBuilder: (_,
                {VoidCallback onStepContinue, VoidCallback onStepCancel}) {
              return Row(
                children: <Widget>[
                  RaisedButton(
                    color: Colors.blue,
                    shape: CircleBorder(
                      side: BorderSide(width: 2.0, color: Color(0xFFFFDFDFDF)),
                    ),
                    onPressed: onStepContinue,
                    child: Icon(
                      Icons.check,
                      color: Colors.white,
                    ),
                  ),
                  RaisedButton(
                    color: Colors.red,
                    shape: CircleBorder(
                      side: BorderSide(width: 2.0, color: Color(0xFFFFDFDFDF)),
                    ),
                    onPressed: onStepCancel,
                    child: Icon(
                      Icons.keyboard_backspace,
                      color: Colors.white,
                    ),
                  ),
                ],
              );
            },
            steps: stepsData.keys.map((e){
              bool isActive = stepsData.keys.toList().indexOf(e) ==_position;
              return Step(
              title: Text(e,style: TextStyle(color: isActive?Colors.blue:Colors.black),),
              isActive: isActive,
              state: _getState(stepsData.keys.toList().indexOf(e)),
              content: Container(height: 60, child: Text(stepsData[e])),
            );
            }).toList()),
      );
    }
    _getState(index){
      if(_position==index) return StepState.editing;
      if(_position>index) return StepState.complete;
      return StepState.indexed;
    }
  }


name: Stepper的方向
subtitle: 【type】 : 方向 【StepperType】
code:
  class VerticalStepper extends StatefulWidget {
    @override
    _VerticalStepperState createState() => _VerticalStepperState();
  }

  class _VerticalStepperState extends State<VerticalStepper> {
    int _position = 0;

    final stepsData = {
      "填写表单":'请按表单填写个人信息。',
      "邮箱校验":'已将邮件发送至您的邮箱，请按照相关指示对您的账号进行邮箱校验。',
      "注册完成":'恭喜您，注册完成！',
    };

    final steps = [
      Step(
        title: Text("填写表单"),
        content: Container(height: 60, child: Text("请按表单填写个人信息")),
      ),
      Step(title: Text("邮箱校验"), content: Text("请对您的账号进行邮箱校验")),
      Step(title: Text("注册完成"), content: Text("恭喜您，注册完成")),
    ];

    @override
    Widget build(BuildContext context) {
      return Container(
        child: Stepper(
            type:StepperType.vertical,
            currentStep: _position,
            onStepTapped: (index) {
              setState(() {
                _position = index;
              });
            },
            onStepContinue: () {
              setState(() {
                if (_position < 2) {
                  _position++;
                }
              });
            },
            onStepCancel: () {
              if (_position > 0) {
                setState(() {
                  _position--;
                });
              }
            },
            controlsBuilder: (_,
                {VoidCallback onStepContinue, VoidCallback onStepCancel}) {
              return Row(
                children: <Widget>[
                  RaisedButton(
                    color: Colors.blue,
                    shape: CircleBorder(
                      side: BorderSide(width: 2.0, color: Color(0xFFFFDFDFDF)),
                    ),
                    onPressed: onStepContinue,
                    child: Icon(
                      Icons.check,
                      color: Colors.white,
                    ),
                  ),
                  RaisedButton(
                    color: Colors.red,
                    shape: CircleBorder(
                      side: BorderSide(width: 2.0, color: Color(0xFFFFDFDFDF)),
                    ),
                    onPressed: onStepCancel,
                    child: Icon(
                      Icons.keyboard_backspace,
                      color: Colors.white,
                    ),
                  ),
                ],
              );
            },
            steps: stepsData.keys.map((e){
              bool isActive = stepsData.keys.toList().indexOf(e) ==_position;
              return Step(
                title: Text(e,style: TextStyle(color: isActive?Colors.blue:Colors.black),),
                isActive: isActive,
                state: _getState(stepsData.keys.toList().indexOf(e)),
                content: Container(height: 60, child: Text(stepsData[e])),
              );
            }).toList()),
      );
    }
    _getState(index){
      if(_position==index) return StepState.editing;
      if(_position>index) return StepState.complete;
      return StepState.indexed;
    }
  }


name: AnimatedAlign基本使用
subtitle:
  【child】 : 孩子组件   【Widget】
  【duration】 : 动画时长   【Duration】
  【alignment】 : 对齐方式   【AlignmentGeometry】
  【curve】 : 动画曲线   【Duration】
  【vsync】 : vsync   【TickerProvider】

code:
  class CustomAnimatedSize extends StatefulWidget {
    @override
    _CustomAnimatedSizeState createState() => _CustomAnimatedSizeState();
  }

  class _CustomAnimatedSizeState extends State<CustomAnimatedSize>
      with SingleTickerProviderStateMixin {
    final double start = 100;
    final double end = 200;

    double _width;

    @override
    void initState() {
      _width = start;
      super.initState();
    }

    @override
    Widget build(BuildContext context) {
      return Column(
        children: <Widget>[
          _buildSwitch(),
          Container(
            color: Colors.grey.withAlpha(22),
            width: 200,
            height: 100,
            alignment: Alignment.center,
            child: AnimatedSize(
              vsync: this,
              duration: Duration(seconds: 1),
              curve: Curves.fastOutSlowIn,
              alignment: Alignment(0, 0),
              child: Container(
                height: 40,
                width: _width,
                alignment: Alignment.center,
                color: Colors.blue,
                child: Text(
                  '张风捷特烈',
                  style: TextStyle(color: Colors.white),
                ),
              ),
            ),
          ),
        ],
      );
    }

    Widget _buildSwitch() => Switch(
        value: _width == end,
        onChanged: (v) {
          setState(() {
            _width = v ? end : start;
          });
        });
  }


name: 径向渐变着色
subtitle:
  【child】 : 孩子组件   【Widget】
  【shaderCallback】 : 着色器回调   【ShaderCallback】
  【blendMode】 : 混色模式   【BlendMode】
      通过RadialGradient#createShader创建径向渐变着色器。

code:
  class RadialShaderMask extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return Wrap(
        spacing: 20,
        crossAxisAlignment: WrapCrossAlignment.center,
        children: <Widget>[
          ShaderMask(
            shaderCallback: _buildShader,
            child: Image.asset(
              'assets/images/icon_head.png',
              height: 70,
              width: 70,
            ),
          ),
          ShaderMask(
            shaderCallback: _buildShader,
            child: Text(
              '张风捷特烈',
              style: TextStyle(fontSize: 40, color: Colors.white),
            ),
          ),
          ShaderMask(
            shaderCallback: _buildShader,
            child: Container(
              height: 100,
              color: Colors.white,
              width: 50,
            ),
          ),
        ],
      );
    }

    final colors = [Colors.red, Colors.yellow, Colors.blue];

    Shader _buildShader(Rect bounds) =>
        RadialGradient(
            center: Alignment.topLeft,
            radius: 1.0,
            tileMode: TileMode.mirror,
            colors: colors)
            .createShader(bounds);
  }


name: 线性渐变着色
subtitle:
  通过LinearGradient#createShader创建线性渐变着色器
  着色器相关知识详见【绘制专辑】

code:
  class LinearShaderMask extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return Wrap(
        spacing: 20,
        crossAxisAlignment: WrapCrossAlignment.center,
        children: <Widget>[
          ShaderMask(
            shaderCallback: _buildShader,
            child: Image.asset(
              'assets/images/icon_head.png',
              height: 70,
              width: 70,
            ),
          ),
          ShaderMask(
            shaderCallback: _buildShader,
            child: Text(
              '张风捷特烈',
              style: TextStyle(fontSize: 40, color: Colors.white),
            ),
          ),
          ShaderMask(
            shaderCallback: _buildShader,
            child: Container(
              height: 100,
              color: Colors.white,
              width: 50,
            ),
          ),
        ],
      );
    }

    final colors = [Colors.red, Colors.yellow, Colors.blue];

    Shader _buildShader(Rect bounds) => LinearGradient(
            begin: Alignment.centerLeft,
            end: Alignment.centerRight,
            tileMode: TileMode.mirror,
            colors: colors)
        .createShader(bounds);
  }


name: DefaultTextStyle使用
subtitle:
  各属性同Text，详见之。
  其功能是: 设置默认的文字样式应用于【后代组件】,注意后代组件也可以指定自身的样式

code:
  class DefaultTextStyleDemo extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return DefaultTextStyle(
        style: TextStyle(
            fontSize: 18,
            color: Colors.blue,
            decoration: TextDecoration.underline),
        child: Wrap(
          spacing: 5,
          children: <Widget>[
            Text("Hello,",),
            FlutterLogo(),
            Text("Flutter",style: TextStyle(color: Colors.red),),
            Text("Unit."),
          ],
        ),
      );
    }
  }


name: IconTheme使用
subtitle: 可以通过IconTheme.of获取图标主题数据，也可以为IconTheme【后代】的图标组件设置默认样式，包括颜色、透明度、尺寸。
code:
  class IconThemeDemo extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return IconTheme(
        data: IconThemeData(
          color: Colors.purple,
          opacity: 1.0,
          size: 30
        ),
        child: Wrap(
          spacing: 5,
          children: <Widget>[
            Icon(Icons.add),
            Icon(Icons.ac_unit),
            Icon(Icons.remove)
          ],
        ),
      );
    }
  }


name: ButtonTheme使用
subtitle: 属性参数同MaterialButton，可以通过ButtonTheme.of获取按钮主题数据，也可以为ButtonTheme【后代】的按钮组件设置默认样式，包括颜色、形状、尺寸等。
code:
  class ButtonThemeDemo extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return ButtonTheme(
        buttonColor: Colors.orange,
        splashColor: Colors.blue,
        minWidth: 40,
        shape: CircleBorder(
          side: BorderSide(width: 2.0, color: Color(0xFFFFDFDFDF)),
        ),
        child: Wrap(
          spacing: 10,
          children: <Widget>[
            RaisedButton(onPressed: (){},child: Icon(Icons.add)),
            FlatButton(onPressed: (){},child: Icon(Icons.add)),
            OutlineButton(onPressed: (){},child: Icon(Icons.add)),
            MaterialButton(onPressed: (){},child: Icon(Icons.add)),
          ],
        ),
      );
    }
  }


name: DividerTheme使用
subtitle: 属性参数与Divider类似，可以通过DividerTheme.of获取分割线主题数据，也可以为DividerTheme【后代】的分割线设置默认样式，包括颜色、粗细、高度等。
code:
  class DividerThemeDemo extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return DividerTheme(
        data: DividerThemeData(
          color: Colors.orange,
          thickness: 2,
          space: 10,
          indent: 10,
          endIndent: 10,

        ),
        child: Wrap(
          spacing: 10,
          children: <Widget>[
           Divider(),
           Divider(),
           Divider(),
           Divider(),
           Divider(),
            Container(
              height: 100,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  VerticalDivider(),
                  VerticalDivider(),
                  VerticalDivider(),
                  VerticalDivider(),
                  VerticalDivider(),
                ],
              ),
            )
          ],
        ),
      );
    }
  }


name: SliderTheme使用
subtitle: 可通过SliderTheme.of获取Slider主题数据对象，其中包含大量属性用于对Slider的设定。可以为ButtonTheme【后代】的按钮组件设置默认样式，包括颜色、形状、尺寸等。
code:
  class SliderThemeDemo extends StatefulWidget {
    @override
    _SliderThemeDemoState createState() => _SliderThemeDemoState();
  }

  class _SliderThemeDemoState extends State<SliderThemeDemo> {
    var _bliss = 0.5;

    @override
    Widget build(BuildContext context) {
      return SliderTheme(
        data: SliderTheme.of(context).copyWith(activeTrackColor: Colors.orange),
        child: Slider(
          min: 0.0,
          max: 200.0,
          divisions: 10,
          label: "${_bliss.toStringAsFixed(1)}",
          onChanged: (double value) {
            setState(() {
              _bliss = value;
            });
          },
          value: _bliss,
        ),
      );
      ;
    }
  }


name: SliderTheme对Slider的样式定制
subtitle: 通过thumbShape和valueIndicatorShape可以对Slider进行样式定制。注: 本例参考flutter-gallery中的SlideDemo
code:
  class DIYSliderTheme extends StatefulWidget {
    @override
    _DIYSliderThemeState createState() => _DIYSliderThemeState();
  }

  class _DIYSliderThemeState extends State<DIYSliderTheme> {
    var _bliss = 0.5;

    @override
    Widget build(BuildContext context) {
      final ThemeData theme = Theme.of(context);

      return SliderTheme(
        data: theme.sliderTheme.copyWith(
          activeTrackColor: Colors.deepPurple,
          inactiveTrackColor: Colors.blue.withAlpha(55),
          activeTickMarkColor: theme.colorScheme.onSurface.withOpacity(0.7),
          inactiveTickMarkColor: theme.colorScheme.surface.withOpacity(0.7),
          overlayColor: theme.colorScheme.onSurface.withOpacity(0.12),
          thumbColor: Colors.deepPurple,
          valueIndicatorColor: Colors.deepPurpleAccent,
          thumbShape: _CustomThumbShape(),
          valueIndicatorShape: _CustomValueIndicatorShape(),
          valueIndicatorTextStyle: theme.accentTextTheme.body2
              .copyWith(color: theme.colorScheme.onSurface),
        ),
        child: Slider(
          min: 0.0,
          max: 200.0,
          divisions: 10,
          label: "${_bliss.toStringAsFixed(1)}",
          onChanged: (double value) {
            setState(() {
              _bliss = value;
            });
          },
          value: _bliss,
        ),
      );
    }
  }

  class _CustomThumbShape extends SliderComponentShape {
    static const double _thumbSize = 4.0;
    static const double _disabledThumbSize = 3.0;

    @override
    Size getPreferredSize(bool isEnabled, bool isDiscrete) {
      return isEnabled
          ? const Size.fromRadius(_thumbSize)
          : const Size.fromRadius(_disabledThumbSize);
    }

    static final Animatable<double> sizeTween = Tween<double>(
      begin: _disabledThumbSize,
      end: _thumbSize,
    );

    @override
    void paint(
      PaintingContext context,
      Offset thumbCenter, {
      Animation<double> activationAnimation,
      Animation<double> enableAnimation,
      bool isDiscrete,
      TextPainter labelPainter,
      RenderBox parentBox,
      SliderThemeData sliderTheme,
      TextDirection textDirection,
      double value,
    }) {
      final Canvas canvas = context.canvas;
      final ColorTween colorTween = ColorTween(
        begin: sliderTheme.disabledThumbColor,
        end: sliderTheme.thumbColor,
      );
      final double size = _thumbSize * sizeTween.evaluate(enableAnimation);
      final Path thumbPath = _downTriangle(size, thumbCenter);
      canvas.drawPath(
          thumbPath, Paint()..color = colorTween.evaluate(enableAnimation));
    }
  }

  Path _upTriangle(double size, Offset thumbCenter) =>
      _downTriangle(size, thumbCenter, invert: true);

  Path _downTriangle(double size, Offset thumbCenter, {bool invert = false}) {
    final Path thumbPath = Path();
    final double height = sqrt(3.0) / 2.0;
    final double centerHeight = size * height / 3.0;
    final double halfSize = size / 2.0;
    final double sign = invert ? -1.0 : 1.0;
    thumbPath.moveTo(
        thumbCenter.dx - halfSize, thumbCenter.dy + sign * centerHeight);
    thumbPath.lineTo(thumbCenter.dx, thumbCenter.dy - 2.0 * sign * centerHeight);
    thumbPath.lineTo(
        thumbCenter.dx + halfSize, thumbCenter.dy + sign * centerHeight);
    thumbPath.close();
    return thumbPath;
  }

  class _CustomValueIndicatorShape extends SliderComponentShape {
    static const double _indicatorSize = 4.0;
    static const double _disabledIndicatorSize = 3.0;
    static const double _slideUpHeight = 30.0;

    @override
    Size getPreferredSize(bool isEnabled, bool isDiscrete) {
      return Size.fromRadius(isEnabled ? _indicatorSize : _disabledIndicatorSize);
    }

    static final Animatable<double> sizeTween = Tween<double>(
      begin: _disabledIndicatorSize,
      end: _indicatorSize,
    );

    @override
    void paint(
      PaintingContext context,
      Offset thumbCenter, {
      Animation<double> activationAnimation,
      Animation<double> enableAnimation,
      bool isDiscrete,
      TextPainter labelPainter,
      RenderBox parentBox,
      SliderThemeData sliderTheme,
      TextDirection textDirection,
      double value,
    }) {
      final Canvas canvas = context.canvas;
      final ColorTween enableColor = ColorTween(
        begin: sliderTheme.disabledThumbColor,
        end: sliderTheme.valueIndicatorColor,
      );
      final Tween<double> slideUpTween = Tween<double>(
        begin: 0.0,
        end: _slideUpHeight,
      );
      final double size = _indicatorSize * sizeTween.evaluate(enableAnimation);
      final Offset slideUpOffset =
          Offset(0.0, -slideUpTween.evaluate(activationAnimation));
      final Path thumbPath = _upTriangle(size, thumbCenter + slideUpOffset);
      final Color paintColor = enableColor
          .evaluate(enableAnimation)
          .withAlpha((255.0 * activationAnimation.value).round());
      canvas.drawPath(
        thumbPath,
        Paint()..color = paintColor,
      );
      canvas.drawLine(
          thumbCenter,
          thumbCenter + slideUpOffset,
          Paint()
            ..color = paintColor
            ..style = PaintingStyle.stroke
            ..strokeWidth = 2.0);
      labelPainter.paint(
          canvas,
          thumbCenter +
              slideUpOffset +
              Offset(-labelPainter.width / 2.0, -labelPainter.height - 4.0));
    }
  }


name: LayoutBuilder基本认识
subtitle: 【builder】 : 布局构造器 【LayoutWidgetBuilder】
code:
  class CustomLayoutBuilder extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      print('CustomLayoutBuild');
      return Container(
        alignment: Alignment.center,
        height: 100,
        width: 150,
        color: Colors.green,
        child: LayoutBuilder(
          builder: (_, zone) {
            return Text(
              '父容器宽:${zone.maxWidth}
  '
              '父容器高:${zone.maxHeight}',
              style: TextStyle(color: Colors.white, fontSize: 16),
            );
          },
        ),
      );
    }
  }


name: LayoutBuilder的适应布局
subtitle: 可以根据区域的大小进行组件展示设计。比如在不同的宽度区域显示不同的布局结构。毕竟很多地方不容易获取父组件区域，使用LayoutBuilder就会非常爽口。
code:
  class FitByLayoutBuilder extends StatefulWidget {
    @override
    _FitByLayoutBuilderState createState() => _FitByLayoutBuilderState();
  }

  class _FitByLayoutBuilderState extends State<FitByLayoutBuilder> {
    double _width = 100;

    @override
    Widget build(BuildContext context) {
      return Column(
        children: <Widget>[
          Container(
            width: _width,
            child: LayoutBuilder(
              builder: (_, zone) {
                if (zone.maxWidth <= 150) {
                  return _buildType1();
                } else {
                  return _buildType2(zone);
                }
              },
            ),
          ),
          _buildSlider(),
        ],
      );
    }

    Widget _buildSlider() {
      return Slider(
            min: 50,
            max: 300,
            label: "父宽:${_width.toStringAsFixed(1)}",
            value: _width,
            onChanged: (v) => setState(() {
                _width = v;
              }));
    }

    Widget _buildType1() => Container(
          color: Colors.blue,
          child: Column(
            children: <Widget>[
              _buildTitle(),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: _buildContent(),
              ),
            ],
          ),
        );

    Widget _buildType2(BoxConstraints zone) => Container(
          height: 100,
          width: zone.maxWidth,
          color: Colors.orange,
          child: Row(
            children: <Widget>[
              Container(
                margin: EdgeInsets.all(10),
                height: 80,
                width: 30,
                color: Colors.grey,
              ),
              Expanded(child: _buildContent())
            ],
          ),
        );

    Widget _buildTitle() => Container(
          margin: EdgeInsets.only(left: 10, right: 10, top: 10),
          color: Colors.grey,
          height: 30,
        );

    Widget _buildContent() => Wrap(
          runSpacing: 3,
          children: <Widget>[
            Container(
              color: Colors.red,
              height: 30,
            ),
            Container(
              color: Colors.yellow,
              height: 30,
            ),
            Container(
              color: Colors.green,
              height: 30,
            ),
          ],
        );
  }


name: LayoutBuilder的展开使用
subtitle: 使用TextPainter来检测文字的行数，实现展开或收起功能。
code:
  class SimpleExpandableText extends StatefulWidget {

    @override
    createState() => _SimpleExpandableTextState();
  }

  class _SimpleExpandableTextState extends State<SimpleExpandableText> {

    final text = '桃树、杏树、梨树，你不让我，我不让你，都开满了花赶趟儿。'
        '红的像火，粉的像霞，白的像雪。'
        '花里带着甜味儿；闭了眼，树上仿佛已经满是桃儿、杏儿、梨儿。'
        '花下成千成百的蜜蜂嗡嗡地闹着，大小的蝴蝶飞来飞去。'
        '野花遍地是：杂样儿，有名字的，没名字的，散在草丛里，像眼睛，像星星，还眨呀眨的。';

    bool expand = false;
    int maxLines =3;


    final style = TextStyle(fontSize: 15, color: Colors.grey, shadows: [
      Shadow(
          color: Colors.white, offset: Offset(1,1)
      )
    ]);

    @override
    build(context) => Container(
      decoration: BoxDecoration(
          color: Colors.cyanAccent.withAlpha(8),
          borderRadius: BorderRadiusDirectional.all(Radius.circular(20))),
      padding: EdgeInsets.all(15),
      child: LayoutBuilder(builder: (context, size) {

        final painter = TextPainter(
          text: TextSpan(text: text, style: style),
          maxLines: maxLines,
          textDirection: TextDirection.ltr,
        );
        painter.layout(maxWidth: size.maxWidth);
        if (!painter.didExceedMaxLines)
          return Text(text, style: style);

        return Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text(text, maxLines: expand ? null : 3, style: style),
            GestureDetector(
              onTap: () => setState(() {
                  expand = !expand;
                }),
              child: Text(
                expand ? '<< 收起' : '展开 >>',
                style: TextStyle(color: Colors.blue),
              ),
            ),
          ],
        );
      }),
    );
  }


name: IgnorePointer基本使用
subtitle:
  【child】 : 孩子组件 【Widget】
  【ignoring】 : 是否忽视事件 【bool】
  如下,Switch选中时ignoring为true，按钮事件将被锁定，无法点击。

code:
  class CustomIgnorePointer extends StatefulWidget {
    @override
    _CustomIgnorePointerState createState() => _CustomIgnorePointerState();
  }

  class _CustomIgnorePointerState extends State<CustomIgnorePointer> {
    bool _ignore = false;

    @override
    Widget build(BuildContext context) {
      return Container(
        child: Wrap(
          crossAxisAlignment: WrapCrossAlignment.center,
          children: <Widget>[
            IgnorePointer(
              ignoring: _ignore,
              child: _buildButton(),
            ),
            _buildSwitch(),
            Text(!_ignore ? '允许点击' : '点击已锁定')
          ],
        ),
      );
    }

    Widget _buildButton() => RaisedButton(
        color: Theme.of(context).primaryColor,
        child: Text(
          'To About',
          style: TextStyle(color: Colors.white),
        ),
        onPressed: () => DialogAbout.show(context));

    _buildSwitch() => Switch(
        value: _ignore,
        onChanged: (v) {
          setState(() {
            _ignore = v;
          });
        });
  }


name: AbsorbPointer基本使用
subtitle:
  【child】 : 孩子组件 【Widget】
  【absorbing】 : 是否吸收事件 【bool】
  如下,Switch选中时absorbing为true，按钮事件将被吸收，无法点击。

code:
  class CustomAbsorbPointer extends StatefulWidget {
    @override
    _CustomAbsorbPointerState createState() => _CustomAbsorbPointerState();
  }

  class _CustomAbsorbPointerState extends State<CustomAbsorbPointer> {
    bool _absorbing = false;

    @override
    Widget build(BuildContext context) {
      return Container(
        child: Wrap(
          crossAxisAlignment: WrapCrossAlignment.center,
          children: <Widget>[
            GestureDetector(
              onTap: (){
                print('AbsorbPointer');
              },
              child: AbsorbPointer(
                absorbing: _absorbing,
                child: _buildButton(),
              ),
            ),
            _buildSwitch(),
            Text(!_absorbing ? '允许点击' : '事件已被吸收')
          ],
        ),
      );
    }

    Widget _buildButton() => RaisedButton(
        color: Theme.of(context).primaryColor,
        child: Text(
          'To About',
          style: TextStyle(color: Colors.white),
        ),
        onPressed: () => DialogAbout.show(context));

    _buildSwitch() => Switch(
        value: _absorbing,
        onChanged: (v) {
          setState(() {
            _absorbing = v;
          });
        });
  }


name: BackdropFilter基本使用
subtitle:
  【child】 : 孩子组件 【Widget】
  【filter】 : 过滤器 【ImageFilter】
  ImageFilter.blur可以实现高斯模糊，指定x，y模糊因子。

code:
  class CustomBackdropFilter extends StatefulWidget {
    @override
    _CustomBackdropFilterState createState() => _CustomBackdropFilterState();
  }

  class _CustomBackdropFilterState extends State<CustomBackdropFilter> {
    double _sigmaX = 1.2;
    double _sigmaY = 1.2;

    @override
    Widget build(BuildContext context) {
      return Column(
        children: <Widget>[
          Stack(
            children: <Widget>[
              _buildImage(),
              Positioned.fill(
                child: ClipRect(
                  child: BackdropFilter(
                    filter: ImageFilter.blur(sigmaX: _sigmaX, sigmaY: _sigmaY),
                    child: Container(
                      color: Colors.black.withAlpha(0),
                    ),
                  ),
                ),
              )
            ],
          ),
          _buildSliders()
        ],
      );
    }

    Widget _buildImage() {
      return Wrap(
        spacing: 20,
        children: <Widget>[
          Container(
            height: 150,
            width: 150,
            child: Image.asset(
              'assets/images/sabar.jpg',
              fit: BoxFit.cover,
            ),
          ),
          Container(
            height: 150,
            width: 150,
            child: Image.asset(
              'assets/images/wy_200x300.jpg',
              fit: BoxFit.cover,
            ),
          ),
        ],
      );
    }

    Widget _buildSliders() => Column(
          children: <Widget>[
            Slider(
                min: 0,
                max: 4,
                value: _sigmaX,
                divisions: 360,
                label: 'x:' + _sigmaX.toStringAsFixed(1),
                onChanged: (v) {
                  setState(() {
                    _sigmaX = v;
                  });
                }),
            Slider(
                min: 0,
                max: 4,
                value: _sigmaY,
                divisions: 360,
                label: 'beta:' + _sigmaY.toStringAsFixed(1),
                onChanged: (v) {
                  setState(() {
                    _sigmaY = v;
                  });
                })
          ],
        );
  }


