Flutter -- 創(chuàng)建你的第一個(gè)應(yīng)用

上一篇我們已經(jīng)配置完所有的Flutter環(huán)境近哟,那接下來(lái)開始創(chuàng)建第一個(gè)Flutter應(yīng)用。
1.打開IDEA選擇Flutter

Snip20190702_2.png

然后創(chuàng)建項(xiàng)目填寫項(xiàng)目名稱,注意:項(xiàng)目名稱中不能包含大寫字母!!兰英!
Snip20190702_11.png

2.此時(shí)我們可以在項(xiàng)目目錄中找到Android和iOS的項(xiàng)目
Snip20190702_13.png

打開iOS應(yīng)用,創(chuàng)建一個(gè)唯一的bundleID供鸠,能在手機(jī)中運(yùn)行即可
image.png

3.創(chuàng)建文件畦贸,復(fù)制代碼

  • lib下找到mian.dart文件,刪除main下的所有代碼楞捂,替換為下面的代碼
import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Welcome to Flutter',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Welcome to Flutter'),
        ),
        body: new Center(
          child: new Text('Hello World'),
        ),
      ),
    );
  }
}
  • 在項(xiàng)目目錄中找到pubspec.yaml薄坏,在文件中添加
dependencies:
  flutter:
  sdk: flutter
  cupertino_icons: ^0.1.0
  english_words: ^3.1.0

但是在pubspec,yaml中正林,發(fā)現(xiàn)只是缺少english_words: ^3.1.0,添加這行代碼

image.png

然后單擊右上角的 Packages get這樣就會(huì)將依賴包安裝到項(xiàng)目中

pubspec.yaml

控制臺(tái)中會(huì)顯示以下內(nèi)容
image.png

  • 創(chuàng)建一個(gè)有狀態(tài)的StatefulWidget這個(gè)是用于展示ListView,根據(jù)不同的狀態(tài)來(lái)展示不同的狀態(tài)下的ListView颤殴。
import 'package:flutter/widgets.dart';
import 'package:fluttertest/RandomWordsState.dart';
//動(dòng)態(tài)組件類,用于顯示listview
class RandomWords extends StatefulWidget {
  //返回狀態(tài),告訴widget不同情況下如何展示
  @override
  State<StatefulWidget> createState() { 
    return new RandomWordsStat();
  }
}
  • 構(gòu)建ListView 創(chuàng)建 RandomWordsState
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:fluttertest/RandomWords.dart';
import 'package:english_words/english_words.dart';
//State 是當(dāng) Widget 被渲染或者在其生命周期中狀態(tài)改變時(shí)觅廓,能同步讀到相關(guān)信息的對(duì)象。當(dāng)實(shí)例StatefulWidget 時(shí)
// 必須保證能正確使用 State.setState 來(lái)告知該 Widget的狀態(tài)發(fā)生了變化涵但。

class RandomWordsStat extends State<RandomWords>{
  //Dart中加上 _表示私有化
  final _suggestions = <WordPair>[];   //分析 1
  final _saved = new Set<WordPair>();
  final _biggerFont = const TextStyle(fontSize: 18.0);   //分析 2
  @override
  Widget build(BuildContext context) {
    return new Scaffold (
      appBar: new AppBar(
        title: new Text('Startup Name Generator'),
        actions: <Widget>[ //右上角按鈕點(diǎn)擊事件杈绸,跳轉(zhuǎn)到下一個(gè)頁(yè)面,所以要實(shí)現(xiàn)`_pushSaved`這個(gè)方法
          new IconButton(icon: new Icon(Icons.list), onPressed: _pushSaved),
        ],
      ),
      body: _buildSuggestions(),
    );
  }
  Widget _buildSuggestions() {
    return new ListView.builder(
        padding: const EdgeInsets.all(16.0),
        // 對(duì)于每個(gè)建議的單詞對(duì)都會(huì)調(diào)用一次itemBuilder矮瘟,然后將單詞對(duì)添加到ListTile行中
        // 在偶數(shù)行瞳脓,該函數(shù)會(huì)為單詞對(duì)添加一個(gè)ListTile row.
        // 在奇數(shù)行,該函數(shù)會(huì)添加一個(gè)分割線widget澈侠,來(lái)分隔相鄰的詞對(duì)劫侧。
        // 注意,在小屏幕上哨啃,分割線看起來(lái)可能比較吃力烧栋。
        itemBuilder: (context, i) {
          // 在每一列之前,添加一個(gè)1像素高的分隔線widget
          //當(dāng)時(shí)奇數(shù)時(shí)返回true
          if (i.isOdd) return new Divider();

          // 語(yǔ)法 "i ~/ 2" 表示i除以2拳球,但返回值是整形(向下取整)审姓,比如i為:1, 2, 3, 4, 5
          // 時(shí),結(jié)果為0, 1, 1, 2, 2祝峻, 這可以計(jì)算出ListView中減去分隔線后的實(shí)際單詞對(duì)數(shù)量
          final index = i ~/ 2;
          // 如果是建議列表中最后一個(gè)單詞對(duì)
          if (index >= _suggestions.length) {
            // ...接著再生成10個(gè)單詞對(duì)魔吐,然后添加到建議列表
            _suggestions.addAll(generateWordPairs().take(10));
          }
          return _buildRow(_suggestions[index]);
        }
    );
  }

  Widget _buildRow(WordPair pair) {
    final alreadySaved = _saved.contains(pair);
    //listView中的行,相當(dāng)于cell
    return new ListTile(
      title: new Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
      //右邊的圖標(biāo)
      trailing: new Icon(
        alreadySaved ? Icons.favorite : Icons.favorite_border,
        color: alreadySaved ? Colors.red : null,
      ),
      onTap: () {
        setState(() {
          if (alreadySaved) {
            _saved.remove(pair);
          } else {
            _saved.add(pair);
          }
        });
      },
    );
  }
 //右上角跳轉(zhuǎn)
  void _pushSaved() {

    Navigator.of(context).push(  // 分析 1//通過Navigator.of(context).push來(lái)跳轉(zhuǎn)頁(yè)面
      new MaterialPageRoute(  // 分析 2 跳轉(zhuǎn)的話我們需要一個(gè)路由
        builder: (context) {
          final tiles = _saved.map(  //數(shù)據(jù),從set中獲取的數(shù)據(jù)
                (pair) {
              return new ListTile(
                title: new Text(
                  pair.asPascalCase,
                  style: _biggerFont,
                ),
              );
            },
          );
          final divided = ListTile.divideTiles(
            context: context,
            tiles: tiles,
          ).toList();

          return new Scaffold(  // 分析 3 將要跳轉(zhuǎn)的頁(yè)面,body的內(nèi)容是一個(gè)listView.展示的數(shù)據(jù)
            appBar: new AppBar(
              title: new Text('Saved Suggestions'),
            ),
            body: new ListView(children: divided),
          );
        },
      ),
    );
  }
}

在此處可以看到莱找,onTap時(shí)調(diào)用了state.setState酬姆,這時(shí)會(huì)告訴框架重繪RandomWords這個(gè)widget

  • 在main.dart中
import 'package:flutter/material.dart';
import 'package:fluttertest/RandomWords.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Startup Name Generator',
      home: new RandomWords(),
    );
  }
}

此時(shí)我們就可以在手機(jī)上運(yùn)行項(xiàng)目了。


Jul-03-2019 18-14-42.gif

雖說(shuō)這個(gè)小demo已經(jīng)出來(lái)了奥溺,但還是有一些不太了解的地方辞色,下面列出了我覺得需要注意的地方。

  • 首先我們需要知道main.dart是程序的入口文件谚赎,類似iOS的AppDelegate文件淫僻,而在main文件中诱篷,默認(rèn)執(zhí)行的第一行代碼就是
    void main() => runApp(new MyApp());壶唤,也就是會(huì)最先執(zhí)行下面的代碼
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Startup Name Generator',
      home: new RandomWords(),
    );
  }
}
  • StatelessWidget StatefulWidget這兩個(gè)是什么鬼,有什么區(qū)別棕所?

    • StatelessWidget 是只有一種狀態(tài)的組件闸盔,我理解的意思是不會(huì)變化的控件
    • StatefulWidget 是有多種狀態(tài)的組件,例如在demo中琳省,點(diǎn)擊的心形按鈕發(fā)生改變迎吵,state的改變就會(huì)引起StatefulWidget的重繪
  • Widget build(BuildContext context) 重寫這個(gè)函數(shù)是干什么躲撰?BuildContext的作用是什么?

    • 首先要先解釋widget击费,這個(gè)可以理解為iOS中的基礎(chǔ)控件UIVIiew拢蛋,存放渲染內(nèi)容、視圖布局信息蔫巩。然而Widget build就是起構(gòu)建的方法谆棱,返回的Scaffold就是widget的布局信息。
    • BuildContext看下文檔就知道這是一個(gè)抽象類圆仔,所以抽象類是不能直接調(diào)用方法的垃瞧,implement 或者extend都可以
      image.png

      再往上翻,我們會(huì)看到BuildContext的介紹坪郭,A handle to the location of a widget in the widget tree.个从,翻譯過來(lái)就是widget在widget樹中位置的句柄,句柄是widget資源歪沃、內(nèi)存的標(biāo)示號(hào)嗦锐,所以我理解通過這個(gè)BuildContext可以獲取或者更新對(duì)應(yīng)的widget
  • 關(guān)于Set沪曙,這里默認(rèn)繼承的是LinkedHashSet意推,是按照元素插入的順序迭代的,所以是有序的珊蟀,而不是HashSet菊值,因?yàn)?code>HashSet是無(wú)序的。

  • WordPair 你可以把他理解為變異的String育灸,當(dāng)然是有所不同的腻窒,WordPair是兩個(gè)String的拼接,在初始化的時(shí)候就已經(jīng)將first second賦值了磅崭。

asPascalCase          first和seconde首字母大寫
asString              返回原始的string儿子,不做修改
asLowerCase           first 和second的首字母都是大寫
asUpperCase           所有字母都大寫
asCamelCase        first首字母小寫,second首字母大寫

邊學(xué)習(xí)邊記錄砸喻。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末柔逼,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子割岛,更是在濱河造成了極大的恐慌愉适,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件癣漆,死亡現(xiàn)場(chǎng)離奇詭異维咸,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門癌蓖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)瞬哼,“玉大人,你說(shuō)我怎么就攤上這事租副∽浚” “怎么了?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵用僧,是天一觀的道長(zhǎng)讨越。 經(jīng)常有香客問我,道長(zhǎng)永毅,這世上最難降的妖魔是什么把跨? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮沼死,結(jié)果婚禮上着逐,老公的妹妹穿的比我還像新娘。我一直安慰自己意蛀,他們只是感情好耸别,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著县钥,像睡著了一般秀姐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上若贮,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天省有,我揣著相機(jī)與錄音,去河邊找鬼谴麦。 笑死蠢沿,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的匾效。 我是一名探鬼主播舷蟀,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼面哼!你這毒婦竟也來(lái)了野宜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤魔策,失蹤者是張志新(化名)和其女友劉穎匈子,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體代乃,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡旬牲,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年仿粹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了搁吓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片原茅。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖堕仔,靈堂內(nèi)的尸體忽然破棺而出擂橘,到底是詐尸還是另有隱情,我是刑警寧澤摩骨,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布通贞,位于F島的核電站,受9級(jí)特大地震影響恼五,放射性物質(zhì)發(fā)生泄漏昌罩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一灾馒、第九天 我趴在偏房一處隱蔽的房頂上張望茎用。 院中可真熱鬧,春花似錦睬罗、人聲如沸轨功。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)古涧。三九已至,卻和暖如春花盐,著一層夾襖步出監(jiān)牢的瞬間羡滑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工算芯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留啄栓,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓也祠,卻偏偏與公主長(zhǎng)得像昙楚,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子诈嘿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

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