Flutter基础小组件(Widgets)

项目演示github地址

Flutter 的界面基本由Widgets组成,widget需要位于MaterialApp内才能正常显示。

Flutter提供了许多widgets,可帮助您构建遵循Material Design的应用程序。
Material应用程序以MaterialApp widget开始, 该widget在应用程序的根部创建了一些有用的widget,其中包括一个Navigator, 它管理由字符串标识的Widget栈(即页面路由栈)。可以让您的应用程序在页面之间的平滑的过渡。 是否使用MaterialApp完全是可选的,但是使用它是一个很好的做法。

  • 应用程序继承了 StatelessWidget,这将会使应用本身也成为一个widget。 在Flutter中,大多数东西都是widget,包括对齐(alignment)、填充(padding)和布局(layout)

  • Scaffold 是 Material library 中提供的一个widget, 它提供了默认的导航栏、标题和包含主屏幕widget树的body属性。widget树可以很复杂。

Flutter有一套丰富、强大的基础widget,其中以下是很常用的:

  • Text该 widget 可让创建一个带格式的文本。
    设置文字&文字大小&颜色&行数限制&文本对齐
const Text(  "hello flutter!",
            textAlign: TextAlign.center,
            maxLines: 1,
            overflow: TextOverflow.ellipsis, // 溢出显示。。。
            style: TextStyle(fontSize: 30.0,// 文字大小
               color: Colors.yellow),// 文字颜色
          ),
  • Row 、Column 这些具有弹性空间的布局类Widget可让您在水平(Row)和垂直(Column)方向上创建灵活的布局。其设计是基于web开发中的Flexbox布局模型。
//水平布局
Widget buildColumns() {
  Row column = new Row(
    children: [
      new Text('hello'),
      new Icon(Icons.mail),
    ],
  );
  return column;
}

//垂直布局
Widget buildColumns1() {
  Column column = new Column(
    children: [
      new Icon(Icons.info),
      new Icon(Icons.mail),
    ],
  );
  return column;
}
  • Stack: 取代线性布局 (译者语:和Android中的LinearLayout相似),Stack允许子 widget 堆叠, 你可以使用 Positioned 来定位他们相对于Stack的上下左右四条边的位置。Stacks是基于Web开发中的绝度定位(absolute positioning )布局模型设计的。

  • Container: Container可让您创建矩形视觉元素。container 可以装饰为一个BoxDecoration,
    Flutter的设计思想就是完全的widget化。这也就是说连最基本的padding,Center都是widget。设想一下如果每次写view,连padding,Center都要自己包一个组件是一种怎样的体验?作为一个工程师,别给只给我谈思想,实际操作的操作效率也同样非常重要。flutter 官方也意识到了这个问题,他们从实际编写效率的角提供了一个友好高效的封装,这就是Container!首先没有任何疑问,Container 本身也是一个widget。但是他却提供了对基础widget的封装,提高了UI基础装饰能力的表达效率。Container类似于android中的ViewGroup。
    它是一个组合的widget,内部有绘制widget、定位widget、尺寸widget。后续看到的不少widget,都是通过一些更基础的widget组合而成的。

Container的组成如下:Container参考文章

最里层的是child元素;
child元素首先会被padding包着;
然后添加额外的constraints限制;
最后添加margin。

Container的绘制的过程如下:

首先会绘制transform效果;
接着绘制decoration;
然后绘制child;
最后绘制foregroundDecoration。

  • 装饰
    Decoration是对Container进行装饰的描述。其概念类似与android中的shape。一般实际场景中会使用他的子类BoxDecoration。BoxDecoration提供了对背景色,边框,圆角,阴影和渐变等功能的定制能力。
    需要注意几个点:

BoxDecoration的image属性相当于设置的是背景图。但是image会绘制在color 和gradient之上。
image是需要一个DecorationImage类的实现。DecorationImage的属性和Image组件比较类似,可以复用Image组件中的ImageProvider。

  • 大小
    BoxConstraints其实是对Container组件大小的描述。BoxConstraints属性比较简单。如果不太清楚可以研究一下盒子模型。这里有个点需要重点说明一下:

如何表达尽可能大这样的意思?(类似于android中的match_parent)Flutter中可以使用double.infinity来做出类似的表达。

  • 实践Coding

设置边框&padding&margin&圆角&背景图

new Container(
         alignment: Alignment.center,
         padding: const EdgeInsets.all(15.0),
         margin: const EdgeInsets.all(15.0),
         decoration: new BoxDecoration(
           border: new Border.all(
             color: Colors.red,
           ),
           image: const DecorationImage(
             image: const NetworkImage(
               'https://gw.alicdn.com/tfs/TB1CgtkJeuSBuNjy1XcXXcYjFXa-906-520.png',
             ),
             fit: BoxFit.contain,
           ),
           //borderRadius: const BorderRadius.all(const Radius.circular(6.0)),
           borderRadius: const BorderRadius.only(
             topLeft: const Radius.circular(3.0),
             topRight: const Radius.circular(6.0),
             bottomLeft: const Radius.circular(9.0),
             bottomRight: const Radius.circular(0.0),
           ),
         ),
         child: Text(''),
       ),

Scaffold是Material中主要的布局组件,现在来看看Scaffold的几个重要属性:

1、appBar appBar显示在Scaffold的顶部。

appBar: new AppBar(
        title: new Text('Scaffold Widget Demo'),
        centerTitle: true,
        backgroundColor: Colors.red,
      ),


centerTitle:让文本居中显示。默认是居左显示

backgroundColor:导航栏背景颜色

2、backgroundColor 这个是整个Scaffold的背景颜色

3、body 主要内容的视图区域,在这个里面,展示的是你的核心内容

4、bottomNavigationBar 用于显示底部导航栏

5、floatingActionButton 浮动于body右上角的按钮

6、floatingActionButtonLocation 决定floatingActionButton按钮的位置

stack

在实际开发中,还是需要在一些Widgets的上面再覆盖上新的Widgets。这时候就需要层式布局了。这种布局在Native上,以android为例,类似于relativeLayout 或者FrameLayout。在Flutter中使用的是Stack。
实际使用中Stack中的子Widgets分为两种:

positioned

是包裹在组件Positioned中的组件
可以通过Positioned属性灵活定位

non-positioned
没有包裹在Positioned组件中
需要通过父Widget Stack 的属性来控制布局

对于non-positioned children, 我们通过控制Stack的alignment属性来控制对齐方式。Positioned的布局方式类似于H5&weex中的position布局中的absolute布局方式。通过设置距离父组件上下左右的距离,Positioned对象能在Stack布局中更加灵活的控制view的展现方式。

层叠布局

new Container(
            color: Colors.yellow,
            height: 150.0,
            width: 500.0,
            child: new Stack(children: [
              new Container(
                color: Colors.blueAccent,
                height: 50.0,
                width: 100.0,
                alignment: Alignment.center,
                child: Text('unPositioned'),
              ),
              new Positioned(
                  left: 40.0,
                  top: 80.0,
                  child: new Container(
                    color: Colors.pink,
                    height: 50.0,
                    width: 95.0,
                    alignment: Alignment.center,
                    child: Text('Positioned'),
                  )),
            ]))

Visibility

当你看完Flutter Widge文档的时候,我们突然发现一个略显尴尬的问题:组件是否显示怎么控制?貌似所有的组件中都没有这个属性!这不坑了,咋办?
目前看方法无非如下几个:

  • 删除法
    核心将该真实widget或者widget树从renderTree中移除。
    具体到实践级别主要分为两个:

单个组件‘隐藏’自己。在build方法中返回一个空的Container.

@override
Widget build(BuildContext context) {
  return isVisible
      ? Widget //真的Widget
      : new Container(); //空Widget 仅仅占位 并不显示
}

多个child

在父容器的children字段的list中,删除掉对应的cell。

  • Offstage
    Offstage 是一个widget。Offstage的offstage属性设置为true,那么Offstage以及他的child都将不会被绘制到界面上。
sample code如下:
@override
Widget build(BuildContext context) {
  return new Offstage(
          offstage: !isVisible,
          child:child);
}
  • 透明度
    设置widget的透明度,使之不可见。但是这样的方法是副作用的。因为这个对应的widget树是已经经过了完整的layout&paint过程,成本高。同时设置透明度本身也要耗费一定的计算资源,造成了二次浪费。需要注意的是即便变透明了,占据的位置还在。大家慎重选择使用。
    sample code如下:
@override
Widget build(BuildContext context) {
  return new AnimatedOpacity(
        duration: Duration(milliseconds: 10),
        opacity: isVisible ? 1.0 : 0.0,
          child:child);
}

visibility的控制还是比较麻烦的。这是Flutter设计上不符合正常习惯的一个点,需要大家重点关注。

参考链接

Flutter基础小组件(Widgets)_第1张图片

Flutter基础小组件(Widgets)_第2张图片

你可能感兴趣的:(Flutter基础小组件(Widgets))