• 152850

      文章

    • 1250

      評論

    • 6

      友鏈

    • 最近新加了換膚功能,大家多來逛逛吧~~~~
    • 喜歡這個網站的朋友可以加一下QQ群,我們一起交流技術。

    入坑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
    

    可直接將環境變量寫入~/.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 插件

    image

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

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

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

    image

    image

    創建

    按照之前的方法創建一個模板 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軟件包以及其他許多開源軟件包 image
    • 將english_words添加到pubspec.yaml文件中(pubspec文件
    • 管理Flutter應用程序的assets(資源,如圖片、package等)) image
    • 在終端中運行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<RandomWords> {
      @override
      Widget build(BuildContext context) {
        final wordPair = new WordPair.random();
        return new Text(wordPair.asPascalCase);
      }
    }
    class RandomWords extends StatefulWidget {
      @override
      State<StatefulWidget> 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<StatefulWidget> createState() {
        // TODO: implement createState
        return new RandomWordsState();
      }
    }
    class RandomWordsState extends State<RandomWords> {
      final _suggestions = <WordPair>[];
      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屬性添加一個按鈕子組件,由于是復數用 <Widget>[]包裝
    2. 當用戶點擊導航欄中的列表圖標時,建立一個路由并將其推入到導航管理器棧中。此操作會切換頁面以顯示新路由在MaterialPageRoute的builder屬性中構建,builder是一個匿名函數。
     @override
      Widget build(BuildContext context) {
        return new Scaffold(
            appBar: new AppBar(
            actions: <Widget>[
              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),
          );
        }));
      }
    

    效果

    image

    image

    使用主題更改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


    695856371Web網頁設計師②群 | 喜歡本站的朋友可以收藏本站,或者加入我們大家一起來交流技術!

    自定義皮膚 主體內容背景
    打開支付寶掃碼付款購買視頻教程
    遇到問題聯系客服QQ:419400980
    注冊梁鐘霖個人博客
    图片区乱小说区电影区