Flutter學(xué)習(xí)筆記(二)

*、assets

當(dāng)引用圖片的時(shí)候抑进,需要在pubspec.yaml的文件中的flutter下添加assets强经,類似于下面的樣子:
image.png

這里需要注意的是文件里的assets只要一個(gè)縮進(jìn)即和flutter里的內(nèi)容保持對(duì)齊,否則单匣,會(huì)出問題夕凝。我遇到的是,沒辦法選擇運(yùn)行設(shè)備户秤。

一码秉、Layout原理

Flutter布局Layout的核心就是Widget。在Flutter里鸡号,基本上任何東西都是Widget转砖,甚至布局的模型。比如images鲸伴、icon府蔗、text等你能在界面上看到的。你看不到的汞窗,如Row姓赤、Column等也是Widget。
復(fù)雜的Widget都是有單個(gè)widget組成的仲吏。

下面是幾個(gè)常用Widget
  • Container:
    容器Widget不铆,允許自己定制一些子widget蝌焚。其初始化如下:
Container({
    Key key,
    this.alignment,
    this.padding,
    Color color,
    Decoration decoration,
    this.foregroundDecoration,
    double width,
    double height,
    BoxConstraints constraints,
    this.margin,
    this.transform,
 })

可以發(fā)現(xiàn),該UI Widget可以控制其中的Widget的padding誓斥、margin以及當(dāng)前widget的寬高只洒、border背景色等等。

  • Row:

    定義一行中的所有Widget和這些Widget的展示方式劳坑,包括主軸方向和副軸方向毕谴,具體的定義如下,其中MainAxisAlignment表示主軸方向(水平方向)距芬,CrossAxisAlignment表示副軸方向(和主軸垂直涝开,即垂直方向):
    row-diagram.png
Row({
    Key key,
    MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start,
    MainAxisSize mainAxisSize: MainAxisSize.max,
    CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center,
    TextDirection textDirection,
    VerticalDirection verticalDirection: VerticalDirection.down,
    TextBaseline textBaseline,
    List<Widget> children: const <Widget>[],
  })
  • Column:

    定義一列中的所有Widget和這些Widget的展示方式,也有主軸和副軸兩個(gè)方向框仔,具體的和Row相同忠寻,其定義如下:
    column-diagram.png
Column({
    Key key,
    MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start,
    MainAxisSize mainAxisSize: MainAxisSize.max,
    CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center,
    TextDirection textDirection,
    VerticalDirection verticalDirection: VerticalDirection.down,
    TextBaseline textBaseline,
    List<Widget> children: const <Widget>[],
  })
ps:主軸和副軸對(duì)于熟悉RN的人應(yīng)該比較好理解

二、Layout Widget(Container存和、MaterialApp、Scaffold)

這里通過一個(gè)HelloWorld app來展示如何創(chuàng)建一個(gè)Widget并展示出來衷旅,并區(qū)分Material和非Material環(huán)境捐腿。
hello_word.dart里的代碼如下:

class HelloWorld {
  static Widget helloWorld() {
    return new MaterialApp(
      title: 'Hello World',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new Scaffold(
        appBar: new AppBar(title: new Text('Hello World')),
        body: new Center(
            child: new Text(
          "Hello World",
          style: new TextStyle(fontSize: 32.0),
        )),
      ),
    );
  }

  static Widget hellWorldWithoutMaterial() {
    return new Container(
      decoration: new BoxDecoration(color: Colors.white),
      child: new Center(
        child: new Text(
          'Hello World',
          textDirection: TextDirection.ltr, // 這一句必須有
          style: new TextStyle(color: Colors.black, fontSize: 40.0),
        ),
      ),
    );
  }
}

而在展示上,主要的區(qū)別在于非Material下柿顶,沒有Appbar茄袖、背景色和標(biāo)題等,所有的內(nèi)容都需要自定義嘁锯。

注意??:

1宪祥、Scaffold必須放在MaterialApp里面,否則會(huì)報(bào)錯(cuò)家乘,大致如下:

══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown building Scaffold(dirty, state: ScaffoldState#6f74d):
No MediaQuery widget found.
Scaffold widgets require a MediaQuery widget ancestor.
The specific widget that could not find a MediaQuery ancestor was:
Scaffold
The ownership chain for the affected widget is:
Scaffold ← MyApp ← [root]
Typically, the MediaQuery widget is introduced by the MaterialApp or WidgetsApp widget at the top of
your application widget tree.

2蝗羊、非Material下Text的textDirection屬性是必須的

??????到底什么是Material App?

三仁锯、在水平和垂直方向上Layout(Row耀找、Column)

1、水平布局:

class LayoutImagesH {
  static layoutImagesH() {
    MaterialApp material = new MaterialApp(
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text(
            "Images H Layout",
            style: new TextStyle(color: Colors.white, fontSize: 20.0),
          ),
        ),
        body: _getLayoutContainer(),
      ),
    );
    return material;
  }

  static _getLayoutContainer() {
    Row row = new Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        _getRowsImage('images/pic1.jpg'),
        _getRowsImage('images/pic2.jpg'),
        _getRowsImage('images/pic3.jpg')
      ],
    );
    Container container = new Container(
      padding: const EdgeInsets.all(15.0),
      color: Colors.grey,
      child: row,
    );
    return container;
  }

  static _getRowsImage(imageStr) {
    return new Image.asset(
      imageStr,
      width: 100.0,
    );
  }
}

2业崖、垂直布局

class LayoutImagesV {
  static layoutImagesVSpaceEvenly() {
    return new Container(
      color: Colors.green,
      child: new Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          new Image.asset('images/pic1.jpg'),
          new Image.asset('images/pic2.jpg'),
          new Image.asset('images/pic3.jpg'),
        ],
      ),
    );
  }
  static layoutImagesVSpaceAround() {
    return new Container(
      color: Colors.green,
      child: new Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          new Image.asset('images/pic1.jpg'),
          new Image.asset('images/pic2.jpg'),
          new Image.asset('images/pic3.jpg'),
        ],
      ),
    );
  }
  static layoutImagesVSpaceBetween() {
    return new Container(
      color: Colors.green,
      child: new Column(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          new Image.asset('images/pic1.jpg'),
          new Image.asset('images/pic2.jpg'),
          new Image.asset('images/pic3.jpg'),
        ],
      ),
    );
  }
}

主軸的枚舉如下:

enum MainAxisAlignment {
  start,
  end,
  center,
  /// 第一個(gè)和最后一個(gè)貼邊野芒,中間的平分
  spaceBetween,
  /// 第一個(gè)和最后一個(gè)距離邊的距離是它與中間的距離的一半
  spaceAround,
  /// 完全平分
  spaceEvenly,
}

四、按比例布局(Expanded)

使用Expanded Widget双炕,它繼承自Flexible狞悲,主要是通過其中flex屬性來控制,默認(rèn)整個(gè)Expanded里的flex都是1妇斤,即平分摇锋。我們可以通過控制flex來控制每個(gè)Widget所占的大小丹拯。

先來看一個(gè)現(xiàn)象:
image.png

邊上黃條是什么鬼,這里用的代碼還是上面提到的水平方向的布局乱投,代碼里只是修改了圖片咽笼,就變成了這個(gè)鬼樣子。

經(jīng)過嘗試戚炫,你會(huì)發(fā)現(xiàn)剑刑,只要總尺寸超過了容器的限制,就會(huì)出現(xiàn)這種問題双肤。要解決這種問題施掏,目前來看,一是控制圖片的尺寸茅糜,一個(gè)就是使用Expanded 的Widget七芭。

代碼如下:

class ExpandedImages {
  static expandedImages() {
    return new Container(
      color: Colors.green,
//      margin: const EdgeInsets.all(15.0),
      child: new Row(
        textDirection: TextDirection.ltr,
//        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: _getRowChildren(),
      ),
    );
  }
  static expandImagesWithMaterial() {
      return new MaterialApp(
        home: new Scaffold(
          appBar: new AppBar(
              title: new Text('Expanded')
          ),
          body: new Center(
            child: new Row(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: _getRowChildren(),
            ),
          )
        ),
      );
  }
  static _getRowChildren() {
    return [
//      new Expanded(child: new Image.asset("images/pic1.jpg")),
//      new Expanded(flex:2, child: new Image.asset("images/pic2.jpg")),
//      new Expanded(child: new Image.asset("images/pic3.jpg"))
      new Expanded(child: new Image.asset("images/expand1.jpg")),
      new Expanded(flex:2, child: new Image.asset("images/expand2.jpg")),
      new Expanded(child: new Image.asset("images/expand3.jpg"))
    ];
  }
}

最后的效果如下圖所示:
image.png

看到這里其實(shí)也明白了,上面的水平方向和垂直方向的布局是有問題的蔑赘。

五狸驳、壓縮空間

一般的Row和Column的布局都是盡可能大的利用Space笋熬,如果此時(shí)不想要這些space验毡,那么可以使用相應(yīng)的mainAxisSize的值來控制汁针,它只有min和max兩個(gè)值,默認(rèn)是max,即我們看見的那種情況卓练。如果設(shè)置了該值為min襟企,那么mainAxisAlignment的后面的幾個(gè)值對(duì)其不再起作用。
下面是測(cè)試代碼:

class _MyHomePageState extends State<_MyHomePage> {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new Scaffold(
      appBar: new AppBar(title: new Text("Packing Widget")),
      body: new Center(
        child: new Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          mainAxisSize: MainAxisSize.min,
//          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            new Icon(Icons.star, color: Colors.green[500]),
            new Icon(Icons.star, color: Colors.green[500]),
            new Icon(Icons.star, color: Colors.green[500]),
            new Icon(Icons.star, color: Colors.grey),
            new Icon(Icons.star, color: Colors.grey),
          ],
        ),
      )
    );
  }
}

六木羹、常用的Widget

總體來說,所有的Widget可以分為兩類:Standard Widget和Material Component。Standard Widget可以在Material App和非Material App中使用,但是Material Component只能在Material App中使用。

1郊愧、Standard Widget

常用的是下面四種:

  • Container
    為Widget添加內(nèi)邊距padding, 外邊距margins, 邊框borders, 背景色background color和其他的一些修飾信息眠寿。
  • GridView
    將其中的Widget按照Grid的形式展示,并且是可滑動(dòng)的。(似乎和UICollectionView相似)。
  • ListView
    將其中的Widget按照List形式展示壤蚜,并且是可滑動(dòng)的。(似乎和UIScrollView、UITableView相似)蟹漓。
  • Stack
    在Widget上覆蓋一個(gè)Widget

2份殿、Material Component

  • Card
  • ListTitle
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市嗽交,隨后出現(xiàn)的幾起案子卿嘲,更是在濱河造成了極大的恐慌,老刑警劉巖夫壁,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拾枣,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡盒让,警方通過查閱死者的電腦和手機(jī)梅肤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來邑茄,“玉大人姨蝴,你說我怎么就攤上這事》温疲” “怎么了左医?”我有些...
    開封第一講書人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)同木。 經(jīng)常有香客問我浮梢,道長(zhǎng),這世上最難降的妖魔是什么彤路? 我笑而不...
    開封第一講書人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任黔寇,我火速辦了婚禮,結(jié)果婚禮上斩萌,老公的妹妹穿的比我還像新娘缝裤。我一直安慰自己屏轰,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開白布憋飞。 她就那樣靜靜地躺著霎苗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪榛做。 梳的紋絲不亂的頭發(fā)上唁盏,一...
    開封第一講書人閱讀 51,727評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音检眯,去河邊找鬼厘擂。 笑死,一個(gè)胖子當(dāng)著我的面吹牛锰瘸,可吹牛的內(nèi)容都是我干的刽严。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼避凝,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼舞萄!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起管削,我...
    開封第一講書人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤倒脓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后含思,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體崎弃,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年含潘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了饲做。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡调鬓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出酌伊,到底是詐尸還是另有隱情腾窝,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布居砖,位于F島的核電站虹脯,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏奏候。R本人自食惡果不足惜循集,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蔗草。 院中可真熱鬧咒彤,春花似錦疆柔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至歇拆,卻和暖如春鞋屈,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背故觅。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來泰國打工厂庇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人输吏。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓权旷,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親评也。 傳聞我的和親對(duì)象是個(gè)殘疾皇子炼杖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容