Flutter学习笔记(五)

一、Container

是一个便利的Widget,它把通用的绘制、定位和Widget的大小结合了起来。
Container会先用padding填充子Widget和border之间的空白,然后添加其他的额外的约束constraints,最后会把剩余的都用margin来填充。
在绘制的过程中,会优先绘制transform,然后是decoration,最后是foregroundDecoration。
对于一个没有子Widget的Container,在没有一些约束的条件时,它会尽可能的大;而一旦有了约束或者子Widget,它就会变得尽可能小。
下面是代码演示时间:

首先基础代码如下:
image.png
后面的每次都是替换图中的方法。
  • 没有任何子Widget时
static _baseContainer() {
    return new Container(
      color: Colors.red,
    );
  }
此时的截图如下:
image.png

 

 

 

 

发现它尽可能的占了全部。
此时,设置padding是不起作用的。

  • 没有其他约束,只有一个子widget时
static _addWidgetToContainer() {
    return new Container(
      color: Colors.red,
      child: new Text("Container"),
    );
  }
此时变成了下面的样子:
image.png

它几乎和子Widget贴合到了一起了。

  • 当限制了宽度的时候
static _limitWidth() {
    return new Container(
      color: Colors.red,
      child: new Text("Container"),
      width: 20.0,
//      width: 200.0,
//      height: 10.0,
    );
  }
可以肯定,文字的宽度要比20大,因为此时没有限制高度,所以会展示成下面的样子:
image.png

可以发现它的高度自动变大了,直到能把所有的内容容纳下来。

当限制了高度的时候

假设这个时候宽度是足够的,如果限制了高度,高度如果足够,则会正常展示,但是如果高度不够的时候就会出现越界的现象,如下所示:
image.png
如果我指定了宽度和高度里的一个,而没有一些约束和子Widget,未指定的会尽可能最大。

当限制了宽和高的时候

可以确定,宽高足够的时候,是能够完美展示的。如果宽度不够,高度也不够呢,会是什么样的展示呢?
image.png
  • 限定宽度或者高度,指定padding
    当padding的宽度超过了width,则会默认保留左padding或者上padding。
  • static _limitWidthWithPadding() {
        return new Container(
          color: Colors.red,
          padding: const EdgeInsets.all(20.0),
          height: 20.0,
          width: 20.0,
          child: new Text("Container"),
        );
      }
    
    image.png
    • contraints约束
    static _boxContraints() {
        return new Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Container(
              // 相当于直接制定了该Container的宽和高,且它的优先级要高于width和height
              constraints: new BoxConstraints.expand(width: 250.0, height: 150.0),
              color: Colors.red,
              width: 100.0,
              height: 100.0,
    // 设置Container的最大和最小宽度和高度
    //          constraints: new BoxConstraints(
    //            maxWidth: 50.0,
    //          ),
            ),
            new Container(
              color: Colors.green,
              width: 100.0,
              height: 100.0,
            )
          ],
        );
      }
    

    这里主要展示了它的默认初始化和指定初始化方法的Expand,其中后者就相当于直接制定了该Container的宽和高。

    foregroundDecoration

    这个比较重要,它会堵在Container的所有子Widget的前面,另外还有一些圆角和背景的问题,具体的见下图:
    image.png

    代码为:
    static _foregroundDecoration() {
        return new Center(
          child: new Container(
            color: Colors.red,
            constraints: new BoxConstraints.expand(width: 300.0, height: 300.0,),
            foregroundDecoration: new BoxDecoration(
              color: Colors.blue,
              border: new Border.all(color: Colors.yellow, width: 5.0,),
              borderRadius: new BorderRadius.all(new Radius.circular(50.0)),
              gradient: new LinearGradient(colors: [Colors.blue, Colors.green]),
            ),
            alignment: Alignment.center,
            child: new Text("Container"),
          ),
        );
      }
    

    可以发现,对于有背景图的Container,只是简单的切圆角是有问题的;而且它还会堵住子Widget。

    decoration

    针对上面提到的会堵住子Widget和切角问题,decoration可以很好的解决问题,不过这里需要注意⚠️:Container的color和该属性不能共存。所以最后的代码和效果图如下:
    image.png
    static _decoration() {
        return new Center(
          child: new Container(
    //        color: Colors.red,  // 不能和decoration共存
            constraints: new BoxConstraints.expand(width: 300.0, height: 300.0,),
            alignment: Alignment.center,
            child: new Text("Container"),
            decoration: new BoxDecoration(
              color: Colors.blue,
              border: new Border.all(color: Colors.yellow, width: 5.0,),
              borderRadius: new BorderRadius.all(new Radius.circular(50.0)),
              gradient: new LinearGradient(colors: [Colors.blue, Colors.green]),
            ),
          ),
        );
      }
    

    二、Row

    Row在前面聊过,最主要注意的一点就是内容不能超过边界,否则会出错误。
    这里补充的是如果使用了Expanded,那么其中的Widget的尺寸就不再起作用。如下:

    static _baseRow() {
        return new Container(
          color: Colors.red,
          height: 300.0,
          child: new Row(
            // 会超出去,展示错误
    //          children: <Widget>[
    //            new Container(width: 200.0, color: Colors.green,),
    //            new Container(width: 200.0, color: Colors.blue,),
    //            new Container(width: 200.0, color: Colors.cyan,),
    //          ],
          children: <Widget>[
            // 使用了Expanded后,尺寸不再起作用
            new Expanded(child: new Container(width: 50.0, color: Colors.green,)),
            new Expanded(child: new Container(width: 100.0, color: Colors.blue,)),
            new Expanded(child: new Container(width: 100.0, color: Colors.cyan,)),
          ],
          ),
        );
      }
    

    这里的使用了Expanded的Container就不会再起作用

    三、Column(同Row)

    四、Text

    有两种初始化方法,Text和Text.rich。

    五、Icon

    Icon是不响应事件的,IconButton可以。

    六、RaisedButton

    通俗的翻译:浮起来的按钮,先看两个截图吧,有个直观的认识:
    正常展示
    按钮正在被点击中

    默认情况下,可以看到被点击中的按钮浮起来了。

    注意⚠️:它有个参数onPressed,如果没有定义回调函数,则无论你怎么设置,该按钮的状态都是失效状态,而且其他所有的属性,只要是和disable无关的,无论怎么设置都不会起作用。

    1、直接初始化

    具体的详细说明如下:

    raisedButtonWithChild() {
        return new Center(
          child: new RaisedButton(
            onPressed: this.clickedRaisedButton,
            color: Colors.green,
            // child: new Text('Raised Button', style: new TextStyle(color: Colors.black),),
            child: new Text(
              'Raised Button',
            ),
            textColor: Colors.white, // 该按钮上的文字颜色,但是前提是不设置字体自身的颜色时才会起作用
            // highlightColor: Colors.yellow,  // 高亮时的背景色
            disabledColor: Colors.deepOrange, // 失效时的背景色
            disabledTextColor: Colors.grey, // 按钮失效时的文字颜色,同样的不能使用文本自己的样式或者颜色时才会 起作用
            splashColor: Colors.purple, // 点击按钮时的渐变背景色,当你不设置高亮背景时才会看的更清楚
            colorBrightness: Brightness.dark, // 这个我也不知道
            elevation: 15.0, // 正常情况下浮动的距离
            highlightElevation: 5.0, // 高亮时的浮动距离(可以尝试将该值设置的比elevation小,看看体验)
            disabledElevation: 50.0,
            padding: const EdgeInsets.all(20.0),
            shape: new Border.all(
              // 设置边框样式
              color: Colors.blue,
              width: 4.0,
              style: BorderStyle.solid,
            ),
            animationDuration: new Duration(
              // 过程时间,最容易观察的是从elevation到highlightElevation,或者相反过程,但是前提是要彻底的按下去,注意其影子的变化
              seconds: 5,
            ),
            onHighlightChanged: this.hightLightChanged, // 可以用来监听按钮的按下和放开过程
            textTheme: ButtonTextTheme.accent,  // 搞不懂这个
          ),
        );
      }
    

    2、重定向icon初始化

    该方法得到的RaisedButton默认有两个Widget,而且是必传的;其他参数都和直接初始化没什么区别。具体的代码如下:

    raisedButtonWithIcon() {
        return new Center(
          child: new RaisedButton.icon(
            onPressed: this.clickedRaisedButton,
            icon: new Icon(Icons.star),
            label: new Text('RaisedButton'),
          ),
        );
      }
    
    效果图如下:
    image.png

    七、AppBar

    这里有个官方的解释图,比较形象的说明了AppBar的结构:
    app_bar.png

    这里因为对其他的Widget还不熟悉,所以暂时没办法做bottom。做了一个效果图,如下所示:
    image.png

    实现这部分的代码如下:
    class AppBarWidget extends StatefulWidget {
      @override
      State<StatefulWidget> createState() => new AppBarState();
    }
    
    class AppBarState extends State<AppBarWidget> {
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        return new MaterialApp(
          debugShowCheckedModeBanner: false, // 在调试期间,右上角的DEBUG字样
          home: new Scaffold(
            appBar: new AppBar(
              title: new Text(
                'AppBar',
                style: new TextStyle(
                  // 设置字体样式
                  color: Colors.white,
                  fontWeight: FontWeight.bold,
                ),
              ), // title
              // centerTitle: true, // 当设置了actions之后,title的位置会发生变化,使用该属性,可以让标题忽略actions占去的空间居中
              // titleSpacing: 0.0,
              elevation: 0.0, // 下部的影子,该值越大,影子越清楚,为0时,不会有影子,和RaisedButton是一样的
              backgroundColor: Colors.cyan, // 背景色
              leading: this.appBarLeading(),
              actions: this.appBarActions(),
              bottom: null,  // 这个先放一放
              // flexibleSpace: new FlexibleSpaceBar(   // 这个有什么用呢????貌似是说只有在appbar的size改变的时候才会起作用
              //   title: new Text('Flexible'),
              //   // centerTitle: false,
              // ),
            ),
          ),
        );
      }
    
      appBarActions() {
        return <Widget>[
          new Container(
            width: 50.0,
            child: new Icon(
              Icons.star_border,
              color: Colors.red,
            ),
          ),
          new Container(
            width: 50.0,
            child: new Icon(Icons.share),
          ),
          new Container(
            color: Colors.orange,
            width: 50.0,
            margin: const EdgeInsets.only(
              left: 5.0,
              right: 5.0,
            ),
            alignment: Alignment.center,
            child: new Text('actions'),
          ),
        ];
      }
    
      // 经过实验发现,leading是限制了大小的
      appBarLeading() {
        return new RaisedButton(
          onPressed: this.clickedLeadingBtn,
          child: new Text(
            'Leading',
          ),
          textColor: Colors.white,
          color: Colors.red,
          elevation: 0.0,
          disabledElevation: 0.0,
          highlightElevation: 0.0,
          // highlightColor: Colors.cyan,
          colorBrightness: Brightness.light,
          splashColor: Colors.red,
          padding: const EdgeInsets.all(5.0),
        );
      }
    
      clickedLeadingBtn() {
        print('Clicked Leading');
      }
    }
    

    八、FlutterLogo

    用来展示Flutter的logo的,真是任性啊,为了一个Logo,专门写了一个Widget。

    具体的效果如下:
    image.png
    代码为:
    class _FlutterLogoState extends State<_FlutterLogoWidget> {
      var _status = 0;
      clickedToChangeStatus() {
        setState(() {
          _status = (_status + 1) % 3;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        FlutterLogoStyle style = FlutterLogoStyle.markOnly;
        if (_status == 1) {
          style = FlutterLogoStyle.horizontal;
        } else if (_status == 2) {
          style = FlutterLogoStyle.stacked;
        }
        return new Center(
          child: new Column(
            children: <Widget>[
              new Container(
                margin: const EdgeInsets.only(
                  top: 30.0,
                  bottom: 30.0,
                ),
                child: new RaisedButton(
                  onPressed: this.clickedToChangeStatus,
                  color: Colors.green,
                  child: new Text('Change Status'),
                ),
              ),
              new FlutterLogo(
                size: 50.0,
                colors: Colors.red, // 图的颜色
                textColor: Colors.orange, // 只对带文字的style起作用
                // style: FlutterLogoStyle.markOnly,  // 只有图
                style: style, // 左图右文
                // style: FlutterLogoStyle.stacked,  // 上图下文
                duration: new Duration(
                  // 当colors、textColor或者style变化的时候起作用
                  seconds: 3,
                ),
                curve: Curves.elasticOut,  // 动画方式
              )
            ],
          ),
        );
      }
    }
    

    九、PlaceHolder

    通俗讲,就是一个用来占位的Widget,提示开发人员,这里需要暂时保留。效果如下:
    image.png

    代码也很简单,甚至不用多写任何东西,只要初始化了就行了。

    new Container(
                width: 100.0,
                margin: const EdgeInsets.only(top: 30.0),
                child: new Placeholder(
                  fallbackWidth: 100.0,
                  fallbackHeight: 100.0,
                  color: Colors.orange,
                ),
              )
    posted @   brave-sailor  阅读(426)  评论(0编辑  收藏  举报
    编辑推荐:
    · SQL Server 2025 AI相关能力初探
    · Linux系列:如何用 C#调用 C方法造成内存泄露
    · AI与.NET技术实操系列(二):开始使用ML.NET
    · 记一次.NET内存居高不下排查解决与启示
    · 探究高空视频全景AR技术的实现原理
    阅读排行:
    · 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
    · AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
    · 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
    · Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
    · 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
    历史上的今天:
    2018-03-14 AngularJS 指令实践指南(二)
    2018-03-14 AngularJS 指令(Directives)实践指南
    2016-03-14 Swift 2.0 封装图片折叠效果
    2016-03-14 IOS Layer的使用
    2016-03-14 使用代码自定义UIView注意一二三
    2014-03-14 Java解析XML汇总(DOM/SAX/JDOM/DOM4j/XPath)
    点击右上角即可分享
    微信分享提示