入坑Flutter ,棄坑React-Native

前言

由於業務需要之前用react-native重寫了公司項目,中間碰到各種坑,莫名其妙紅屏,適配坑,頁面刷新坑,打包坑,熱更新坑.折磨了兩個月終於完成.年初就聽說了Flutter,看一下是用Google的Dart語言,據說是有望代替JavaScript這個一週完成的奇葩.咳咳,看了下國內鹹魚團隊已經在項目中使用了Flutter技術,這是他們的社區社區博文深入理解flutter的編譯原理與優化,想不到竟然如此強大.忍不住就參考官方文檔寫了個demo

Flutter官網

https://flutter.io/get-started/install/

克隆Flutter倉庫

git clone -b beta https://github.com/flutter/flutter.git

配置環境變量

export PUB_HOSTED_URL=https://pub.flutter-io.cn //國內用戶需要設置

export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn //國內用戶需要設置

export PATH= flutter所在目錄/flutter/bin:$PATH

入坑Flutter ,棄坑React-Native

可直接將環境變量寫入~/.bash_profile文件中執行source $HOME/.bash_profile生效(如果未生效請重啟終端或電腦)

配置命令行工具sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer

安裝鏈接設備工具

brew update

brew install --HEAD libimobiledevice

brew install ideviceinstaller ios-deploy cocoapods

pod setup

VScode 配置

搜索dart code安裝dart 插件

入坑Flutter ,棄坑React-Native

快捷鍵 shift + command + p 輸入 ‘doctor’, 然後選擇 ‘Flutter: Run Flutter Doctor’ 驗證操作

入坑Flutter ,棄坑React-Native

同樣 shift + command + p 輸入 ‘flutter’, 然後選擇 ‘Flutter: New Project’ action 創建一個測試項目 vscode 底部展示附加設備

入坑Flutter ,棄坑React-Native

點擊Debug>Start Debugging即可運行項目

入坑Flutter ,棄坑React-Native

入坑Flutter ,棄坑React-Native

創建

按照之前的方法創建一個模板 shift + command + p 輸入 ‘flutter’, 然後選擇 ‘Flutter: New Project’ action

替換 lib/main.dart. 刪除lib / main.dart中的所有代碼,然後替換為下面的代碼,它將在屏幕的中心顯示“Hello World”

//應用入口

//main函數使用了(=>)符號, 這是Dart中單行函數或方法的簡寫

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

class DemoApp 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('Royce and Owen'),

),

),

);

}

}

外部包使用

  • 您可以 在pub.dartlang.org上找到english_words軟件包以及其他許多開源軟件包
入坑Flutter ,棄坑React-Native


  • 將english_words添加到pubspec.yaml文件中(pubspec文件
  • 管理Flutter應用程序的assets(資源,如圖片、package等))
入坑Flutter ,棄坑React-Native


  • 在終端中運行flutter packages get安裝依賴

flutter packages get

Running "flutter packages get" in startup_first... 0.6s

  • 導入import 'package:english_words/english_words.dart';
  • 使用 English words 包生成文本來替換字符串“Hello World”.
  • 修改代碼

class DemoApp extends StatelessWidget {

@override

Widget build(BuildContext context) {

final wordPair = new WordPair.random();

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(wordPair.asUpperCase),

),

),

);

}

}

添加一個 有狀態的部件(Stateful widget)

Stateless widgets 是不可變的, 這意味著它們的屬性不能改變 - 所有的值都是最終的.

Stateful widgets 持有的狀態可能在widget生命週期中發生變化. 實現一個 stateful widget 至少需要兩個類:

  1. 一個 StatefulWidget類。
  2. 一個 State類。 StatefulWidget類本身是不變的,但是 State類在widget生命週期中始終存在.
  • 新建一個組件類RandomWords
  • 新建一個State組件類RandomWordsState

class RandomWordsState extends State {

@override

Widget build(BuildContext context) {

final wordPair = new WordPair.random();

return new Text(wordPair.asPascalCase);

}

}

class RandomWords extends StatefulWidget {

@override

State createState() {

// TODO: implement createState

return new RandomWordsState();

}

}

  • 修改代碼 final wordPair = new WordPair.random(); // 刪除此行

class DemoApp 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 RandomWords(),

),

),

);

}

}

創建一個無限滾動ListView

擴展(繼承)RandomWordsState類,以生成並顯示單詞對列表。 當用戶滾動時,ListView中顯示的列表將無限增長

  1. 在RandomWordsState添加一個變量_suggestions(下劃線前綴標識符,會強制其變成私有的)
  2. 添加一個_biggerFont變量來孔子字體大小
  3. 新建_buildSuggestions()方法 顯示建議的單詞對
  4. 在RandomWordsState中添加一個_buildRow函數
  5. 更新RandomWordsState的build方法以使用_buildSuggestions()
  6. 更新MyApp的build方法

class RandomWords extends StatefulWidget {

@override

State createState() {

// TODO: implement createState

return new RandomWordsState();

}

}

class RandomWordsState extends State {

final _suggestions = [];

final _biggerFont =

const TextStyle(fontSize: 18.0, color: Color.fromARGB(1, 234, 111, 22));

@override

Widget build(BuildContext context) {

return new Scaffold(

appBar: new AppBar(

title: new Text('StartUp'),

),

body: _buildSuggestions());

}

Widget _buildSuggestions() {

return new ListView.builder(

padding: const EdgeInsets.all(16.0),

// 對於每個建議的單詞對都會調用一次itemBuilder,然後將單詞對添加到ListTile行中

// 在偶數行,該函數會為單詞對添加一個ListTile row.

// 在奇數行,該行書湖添加一個分割線widget,來分隔相鄰的詞對。

// 注意,在小屏幕上,分割線看起來可能比較吃力。

itemBuilder: (context, i) {

// 在每一列之前,添加一個1像素高的分隔線widget

if (i.isOdd) return new Divider();

// 語法 "i ~/ 2" 表示i除以2,但返回值是整形(向下取整),比如i為:1, 2, 3, 4, 5

// 時,結果為0, 1, 1, 2, 2, 這可以計算出ListView中減去分隔線後的實際單詞對數量

final index = i ~/ 2;

if (index >= _suggestions.length) {

_suggestions.addAll(generateWordPairs().take(10));

}

return _buildRow(_suggestions[index]);

});

}

Widget _buildRow(WordPair pair) {

return new ListTile(

title: new Text(

pair.asPascalCase,

style: _biggerFont,

),

);

}

}

添加交互

  1. 添加一個 _saved Set(集合) 到RandomWordsState。這個集合存儲用戶喜歡(收藏)的單詞對
  2. 在 _buildRow 方法中添加 alreadySaved來檢查確保單詞對還沒有添加到收藏夾中。
  3. 同時在 _buildRow()中, 添加一個心形 ❤️ 圖標到 ListTiles以啟用收藏功能
  4. 在 _buildRow中讓心形❤️圖標變得可以點擊。如果單詞條目已經添加到收藏夾中, 再次點擊它將其從收藏夾中刪除。當心形❤️圖標被點擊時,函數調用setState()通知框架狀態已經改變。

Widget _buildRow(WordPair pair) {

//判斷是否收藏

final bool alreadySaved = _saved.contains(pair);

return new ListTile(

title: new Text(

pair.asPascalCase,

style: _biggerFont,

),

subtitle: new Text('哈哈哈'),

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);

}

});

},

);

}

導航到新頁面

在Flutter中,導航器管理應用程序的路由棧。將路由推入(push)到導航器的棧中,將會顯示更新為該路由頁面。 從導航器的棧中彈出(pop)路由,將顯示返回到前一個路由。這點類似iOS的導航機制

  1. 給AppBar的actions屬性添加一個按鈕子組件,由於是複數用 []包裝
  2. 當用戶點擊導航欄中的列表圖標時,建立一個路由並將其推入到導航管理器棧中。此操作會切換頁面以顯示新路由在MaterialPageRoute的builder屬性中構建,builder是一個匿名函數。

@override

Widget build(BuildContext context) {

return new Scaffold(

appBar: new AppBar(

actions: [

new IconButton(icon: new Icon(Icons.list), onPressed: _pushSaved)

],

title: new Text('嘿嘿嘿',

style: const TextStyle(

fontSize: 18.0, color: Color.fromRGBO(150, 22, 123, 1.0))),

),

body: _buildSuggestions());

}

void _pushSaved() {

Navigator.of(context).push(new MaterialPageRoute(builder: (context) {

//便利以保存的單詞 創建tile 或者叫(cell,item)

final tiles = _saved.map((pair) {

return new ListTile(

title: new Text(

pair.asPascalCase,

style: _biggerFont,

),

);

});

final divided =

ListTile.divideTiles(context: context, tiles: tiles).toList();

//返回一個新頁面

return new Scaffold(

appBar: new AppBar(

title: new Text('saved Suggestions'),

),

body: new ListView(children: divided),

);

}));

}

效果

入坑Flutter ,棄坑React-Native

入坑Flutter ,棄坑React-Native

使用主題更改UI

創建ThemeData來定義theme

class DemoApp extends StatelessWidget {

@override

Widget build(BuildContext context) {

return new MaterialApp(

title: 'Startup Name Generator',

//主題

theme: new ThemeData(

primaryColor: Colors.orange,

),

home: new RandomWords(),

);

}

}

ThemeData提供相當多的屬性,自定義程度相當高了,不愧是基於OpenGL構建的UI,比起RN自由度高了很多

Material library中的 Colors類也提供了許多可以使用的顏色常量例如Colors.green,Color.fromRGBO(255, 111, 233, 1.0)

部分屬性介紹

accentColor → Color 控件的前景色(旋鈕、文本、覆蓋邊緣效果等)。

accentColorBrightness → Brightness

dividerColor → Color 分隔符和彈窗分隔符的顏色,也用於ListTiles和DataTables的行之間

primaryColor → Color 應用程序主要部分的背景顏色(工具欄,標籤欄等)

以上第一flutterdemo完成.

Dart語法非常類似JS,相比較RN但少了>更加易懂,擁類似state狀態機,熱加載速度很快,C++底層,基於OpenGL,強大的API和文檔支持.

代碼地址https://gitee.com/Royce_he/flutter_demo


分享到:


相關文章: