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,
            ),
          )
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 更多信息請查看flutter layout Layouts Sigle-child layout widgets ...
    one_cup閱讀 28,954評論 1 17
  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標簽默認的外補...
    _Yfling閱讀 13,805評論 1 92
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,349評論 25 708
  • 轉載請聲明 原文鏈接地址 關注公眾號獲取更多資訊 第一部分 HTML 第一章 職業規劃和前景 職業方向規劃定位...
    前端進階之旅閱讀 16,621評論 32 459
  • 為何來簡書 純粹因為閑得蛋疼。 看到主頁說是為了文字的力量,但在這里有力量的文字看到的真的不多。 來簡書干嘛 只F...
    簡書最強者閱讀 212評論 0 1