Flutter 官方入門文檔

本文是官方文檔學習過程的筆記

官方文檔: https://flutter.io/get-started/codelab/

初始化項目

# bash
flutter create myapp
cd myapp
flutter run -d <deviceID>

Hello World

編寫lib/main.dart, 然后在終端按“r”, 刷新app

import "package:flutter/material.dart";

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

// StatelessWidget 組件是內部沒有可變狀態的組件,相當于React-Redux的展示組件
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: "Welcom to Flutter",
      // new Scaffold(), 頁面構造器,返回一個擁有appBar,和body的組件
      // 有點類似iOS的 ViewController
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text("Welcom To Flutter"),
        ),
        body: new Center(
          child: new Text("hello world"),
        ),
      )
    );
  }
}

我們會得到下面這個頁面

Hello world

使用/添加第三方依賴

在pubspec.yaml中加入english_words依賴:

dependencies:
  flutter:
    sdk: flutter

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^0.1.2
  english_words: ^3.1.0

執行命令下載安裝依賴(需要科學上網):

# bash
flutter packages get

修改main.dart:

import "package:flutter/material.dart";
// 添加依賴
import "package:english_words/english_words.dart";

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 隨機生成一個wordPair文字
    final wordPair = new WordPair.random();
    return new MaterialApp(
      title: "Welcom to Flutter",
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text("Welcom To Flutter"),
        ),
        body: new Center(
          // 使用wordPair生成的文字
          child: new Text(wordPair.asPascalCase),
        ),
      )
    );
  }
}

此時,每次刷新app,都會得到不同的文字, 這一段主要是講解了如何引用和使用第三方包

創建ListView

import "package:flutter/material.dart";
import "package:english_words/english_words.dart";

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

class MyApp extends StatelessWidget {
  // build方法相當于React的render函數
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: "Welcom to Flutter",
      home: new RandomWords(),
    );
  }
}

// 這里使用了StatefulWidget組件,相當于React-Redux的容器組件
// 組件內部有狀態可以維護
class RandomWords extends StatefulWidget{
  @override
    State<StatefulWidget> createState() {
      return new RandomWordsState();
    }
}

class RandomWordsState extends State<RandomWords> {
  final _words = <WordPair>[];
  final _biggerFont = const TextStyle(fontSize: 18.0);
  Widget _buildWords(){
    return new ListView.builder(
      padding: const EdgeInsets.all(16.0),
      itemBuilder: (context,i){
        // 如果是奇數就返回一條分割線
        if (i.isOdd) return new Divider();
        // i ~/ 2 向下取整
        final index = i ~/ 2 ;
        if(index >= _words.length) {
          // 往_words數組里添加10個字符對象
          _words.addAll(generateWordPairs().take(10));
        }
        return _buildRow(_words[index]);
      },
    );
  }
  Widget _buildRow(WordPair pair) {
    return new ListTile(
      title: new Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
    );
  }

  // State組件內部也需要重載build方法,build方法相當于React的render函數
  @override
  Widget build(BuildContext context){
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Startup Name Generator"),
      ),
      body: _buildWords(),
    );
  }
}

添加點擊事件

import "package:flutter/material.dart";
import "package:english_words/english_words.dart";

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: "Welcom to Flutter",
      home: new RandomWords(),
    );
  }
}

class RandomWords extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new RandomWordsState();
  }
}

class RandomWordsState extends State<RandomWords> {
  final _words = <WordPair>[];
  final _biggerFont = const TextStyle(fontSize: 18.0);
  final _saved = new Set<WordPair>();
  Widget _buildWords() {
    return new ListView.builder(
      padding: const EdgeInsets.all(16.0),
      itemBuilder: (context, i) {
        if (i.isOdd) return new Divider();
        final index = i ~/ 2;
        if (index >= _words.length) {
          _words.addAll(generateWordPairs().take(10));
        }
        return _buildRow(_words[index]);
      },
    );
  }

  Widget _buildRow(WordPair pair) {
    // 校驗 _saved 是否包含pair對象
    final isSaved = _saved.contains(pair);
    return new ListTile(
      title: new Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
      // cell 尾部組件, 設置為一個Icon
      trailing: new Icon(
        isSaved ? Icons.favorite : Icons.favorite_border,
        color: isSaved ? Colors.red : null,
      ),
      // 當點擊cell時,移除或添加當前行的title進_saved
      onTap: () {
        setState(() {
          if (isSaved) {
            _saved.remove(pair);
          } else {
            _saved.add(pair);
          }
        });
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Startup Name Generator"),
      ),
      body: _buildWords(),
    );
  }
}

如圖,可以渲染了列表,并且點擊cell,表尾部的Icon會切換顏色


頁面跳轉

給appBar添加一個actions,并且創建一個IconButton,點擊使用Navigator推進一個Scaffold組件

import "package:flutter/material.dart";
import "package:english_words/english_words.dart";

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: "Welcom to Flutter",
      home: new RandomWords(),
    );
  }
}

class RandomWords extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new RandomWordsState();
  }
}

class RandomWordsState extends State<RandomWords> {
  final _words = <WordPair>[];
  final _biggerFont = const TextStyle(fontSize: 18.0);
  final _saved = new Set<WordPair>();

  Widget _buildWords() {
    return new ListView.builder(
      padding: const EdgeInsets.all(16.0),
      itemBuilder: (context, i) {
        if (i.isOdd) return new Divider();
        final index = i ~/ 2;
        if (index >= _words.length) {
          _words.addAll(generateWordPairs().take(10));
        }
        return _buildRow(_words[index]);
      },
    );
  }

  Widget _buildRow(WordPair pair) {
    final isSaved = _saved.contains(pair);
    return new ListTile(
      title: new Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
      trailing: new Icon(
        isSaved ? Icons.favorite : Icons.favorite_border,
        color: isSaved ? Colors.red : null,
      ),
      onTap: () {
        setState(() {
          if (isSaved) {
            _saved.remove(pair);
          } else {
            _saved.add(pair);
          }
        });
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
          title: new Text("Startup Name Generator"),
          actions: <Widget>[
            new IconButton(
              icon: new Icon(Icons.list),
              onPressed: () {
                // 實現頁面跳轉的函數
                Navigator
                    .of(context)
                    .push(new MaterialPageRoute(builder: (context) {
                  return new SavedPage(saved: _saved, biggerFont: _biggerFont);
                }));
              },
            )
          ]),
      body: _buildWords(),
    );
  }
}

// 實現已保存數據的頁面
class SavedPage extends StatelessWidget {
  // 聲明類的參數
  SavedPage({@required this.saved, @required this.biggerFont});
  final Set<WordPair> saved;
  final TextStyle biggerFont;

  // 渲染一個列表
  @override
  Widget build(BuildContext context) {
    final divided = ListTile
        .divideTiles(
          context: context,
          tiles: saved.map((pair) {
            return new ListTile(
              title: new Text(
                pair.asPascalCase,
                style: biggerFont,
              ),
            );
          }),
        )
        .toList();
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Saved Words"),
      ),
      body: new ListView(children: divided),
    );
  }
}

如下圖Gif, 頁面已經可以導航了

修改主題

MaterialApp里面有theme屬性,可以設置全局主題

import "package:flutter/material.dart";
import "package:english_words/english_words.dart";

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: "Welcom to Flutter",
      // 這里設置主題
      theme: new ThemeData(
        primaryColor: Colors.green,
        dividerColor: Colors.greenAccent,
      ),
      home: new RandomWords(),
    );
  }
}

如圖,替換了主色和分割線的顏色

green主題

您已經編寫了一個可在iOS和Android上運行的交互式Flutter應用程序。在這個codelab中,你應該已學到了:

  • 從頭開始創建一個Flutter應用程序。
  • 書面Dart代碼。
  • 利用外部的第三方庫。
  • 使用熱重載加快開發周期。
  • 實現一個有狀態的小部件,為你的應用增加交互性。
  • 用ListView和ListTiles創建一個延遲加載的無限滾動列表。
  • 實現了頁面跳轉
  • 了解如何使用主題更改應用UI的外觀。

至此,flutter官方快速入門文檔已結束

參考資料: https://flutter.io/get-started/codelab/

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

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,116評論 25 708
  • 在上一篇教程中說了Flutter使用Dart語言開發。本篇教程整體介紹一下Dart語言,注意,本篇不會介紹Dart...
    lazydu閱讀 5,106評論 3 13
  • “你們聽說了嗎?據說這屆初一的老大是個女生。據說家族挺有勢力的。”“有勢力為啥還要來咱們這個破學校呀?”“聽說是為...
    戰毀星辰閱讀 334評論 0 0
  • 1.莫扎特有完美音高,是因為他父親在他4歲時就開始對他進行各種樂器的有效訓練。 完美音高不是一種天才,可以通過訓練...
    季風中的鳥閱讀 161評論 0 0