Home Flutter 初次上手笔记
Post
Cancel

Flutter 初次上手笔记

1. Flutter 安装

Flutter是Google开源的一套跨平台框架,开发语言是 Dart,目前处于pre-release阶段。

Flutter 安装官方指南:https://flutter.io/get-started/install/


2. 项目结构

Flutter项目结构:

  • android
  • ios
  • lib
  • pubspec.yaml


  • 配置文件pubspec.yaml

    app图标更改貌似只能在android/ios目录下修改原配置文件?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    
    # app name
    name: demo
    description: A new Flutter application.
      
    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
      
    dev_dependencies:
      flutter_test:
        sdk: flutter
      
      
    flutter:
      
      # The following line ensures that the Material Icons font is
      # included with your application, so that you can use the icons in
      # the material Icons class.
      uses-material-design: true
        
      # 资源文件
      assets:
          - images/macat.jpg
    


  • Flutter 的几个特点

    1. 入口函数

    1
    
    void main() => runApp(MyApp());//runApp是内置方法,需传入Widget实例,是程序的入口
    

    2. Flutter中大部分布局相关类都是Widget的子类,像Navigator, Center等。接触到两个相似的类:StatelessWidget, StatefulWidget:

    StatelessWidget:

    它是一个抽象类, 需要实现: Widget build(BuildContext context), 通过它来提供视图。

    从命名就可以看出, 它的state是不能够更改的,即不能通过setState来刷下页面。

    StatefulWidget:

    它的状态时可以更改的,通过方法setState, 可以使自身刷新重绘。(调用setState的widget重绘还是StatefulWidget整重绘?)

    与StatelessWidget不同,StatefulWidget需要实现: createState()方法,返回State<? extends StatefulWidget>继承类,再通过state类的 Widget build(BuildContext context) 方法来提供视图。

    3. Dart语言的特点,在变量前加入下划线,该变量就变成了私有变量

    1
    
    final _biggerFont = const TextStyle(fontSize: 18.0);
    

    4. 由于在配置文件中设置了 uses-material-design: true ,可以直接使用Icons类下的图标

    1
    2
    
    Icons.favorite;
    Icons.favorite_border;
    


  • 接触到的Widget 实现类

    • MaterialApp

    • Scaffold UI布局脚手架,可以设置appbar, body, drawer, bottomNavigation等,大部分的页面布局都可以用它来实现。

      • appBar
      • body
    • Center 让child居中显示,它自身的尺寸是这样的:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      
      This widget will be as big as possible if its dimensions are constrained and
      [widthFactor] and [heightFactor] are null. 
      
      If a dimension is unconstrained
      and the corresponding size factor is null then the widget will match its
      child's size in that dimension. 
      
      If a size factor is non-null then the
      corresponding dimension of this widget will be the product of the child's
      dimension and the size factor. 
      
      For example if widthFactor is 2.0 then
      the width of this widget will always be twice its child's width.
      
    • Navigator

    • ListView

    • ListTile ListView的模板Item

    • Text

      • softWrap 若为false,将视作text主轴上有无限空间,绘制时不会自动换行。若为true,会自动换行。
    • Icon 图标Widget

    • Row,Column

      • children
      • mainAxisAlignment 主轴,column的主轴是Y轴
      • crossAxisAlignment 辅轴,column的辅轴是X轴
      • mainAxisSize
        • MainAxisSize.min 相当于wrap_content
        • MainAxisSize.max 相当于match_parent
    • Expanded 填满主轴的剩余空间;若主轴上有多个Expanded,则按child的factor来分配空间

      • child 必须是 Row/Column/Flex 其中的一种
    • Container 相当于给child widget套上一层容器,布局上可以设置padding/margin/transform等

      • child
      • padding
    • Image

      • 加载asset布局文件

        1
        2
        3
        4
        5
        6
        
        Image.asset(
            'images/macat.jpg',
            width: 600.0,
            height: 240.0,
            fit: BoxFit.cover
        )
        
      • 还有其他用法,好像很厉害的样子(还未研究)

        1
        2
        3
        4
        
        Image.Image();
        Image.network();
        Image.file();
        Image.memory();
        


  • Flutter代码在lib下,例子如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    
    import 'package:demo/demo2.dart';
    import 'package:flutter/material.dart';
    import 'package:english_words/english_words.dart';
      
    void main() => runApp(new MyApp2());
      
    class MyApp extends StatelessWidget {
      
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: "flutter title",
          theme: ThemeData(
              primaryColor: Colors.white
          ),
          home: Scaffold(
            body: Center(
              child: RandomWords()
            ),
          ),
        );
      }
    }
      
    class RandomWords extends StatefulWidget {
      
      createState() => RandomWordsState();
      
    }
      
    class RandomWordsState extends State<RandomWords> {
      final _suggestions = <WordPair>[];
      final _saved = Set<WordPair>();
      final _biggerFont = const TextStyle(fontSize: 18.0);
      
      @override
      Widget build(BuildContext context) {
        return Scaffold (
          appBar: AppBar(
            title: Text('Startup Name Generator'),
            actions: <Widget>[
              IconButton(icon: Icon(Icons.list), onPressed: _pushSaved,)
            ],
          ),
          body: _buildSuggestions(),
        );
      }
      
      void _pushSaved() {
        Navigator.of(context).push(
          MaterialPageRoute(
              builder: (context) {
                final tiles = _saved.map(
                    (item) {
                      return ListTile(
                        title: Text(
                          item.asPascalCase,
                          style: _biggerFont,
                        ),
                      );
                    }
                );
                final divided = ListTile.divideTiles(context: context, tiles: tiles).toList();
                return Scaffold(
                  appBar: AppBar(
                    title: Text('My favorite')
                  ),
                  body: ListView(children: divided,),
                );
              }
          )
        );
      }
      
      Widget _buildSuggestions() {
        return ListView.builder(
            padding: const EdgeInsets.all(16.0),
            itemBuilder: (context, i) {
              if (i.isOdd) return Divider();
      
              final index = i ~/2;
              if (index >= _suggestions.length) {
                _suggestions.addAll(generateWordPairs().take(10));
              }
              return _buildRow(_suggestions[index]);
            }
        );
      }
      
      Widget _buildRow(WordPair suggestion) {
        final alreadySaved = _saved.contains(suggestion);
        return ListTile(
          title: Text(
            suggestion.asPascalCase,
            style: _biggerFont,
          ),
          trailing: Icon(
            alreadySaved ? Icons.favorite : Icons.favorite_border,
            color: alreadySaved ? Colors.red : null,
          ),
          onTap: () {
            setState(() {
              if (alreadySaved) {
                _saved.remove(suggestion);
              } else {
                _saved.add(suggestion);
              }
            });
          },
        );
      }
    }
    


目前只接触到Flutter的冰山一角,等后续再慢慢补充吧!

This post is licensed under CC BY 4.0 by the author.