欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第一个Flutter APP

程序员文章站 2022-05-29 19:45:51
...

创建Flutter App

创建一个新的Flutter项目,项目会默认自带一个示例,编辑lib/main.dart的代码

删除main.dart文件中的代码,替换为以下代码,然后运行

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @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"),
        ),
      ),
    );
  }
}

运行应用程序,设备上看到如下界面:

第一个Flutter APP
- Flutter提供了一套丰富的Material widgets
- main函数使用了=>符号,这是Dart中单行函数的简写
- 应用继承了StatelessWidget,这代表应用本身也是一个widget,在Flutter中,大多数东西都是widget
- Scaffold是Material library中提供的一个widget,它提供了默认导航栏、标题、包含主屏幕widget树的body属性
- widget提供build方法来描述如何根据其他较低级别的widget来显示自己

使用外部包

如何使用开源软件包,这里以english_words为例
1. pubspec文件用来管理Flutter应用的assets,在pubspec.yaml文件中,添加endlish_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
  1. 然后点击上方的Package get,将依赖包安装到项目中
  2. 获取成功之后再main.dart中引入
import 'package:english_words/english_words.dart';
  1. 然后对main.dart项目进行一下更改:
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @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("Hello world"),
        child: new Text(wordPair.asPascalCase),
        ),
      ),
    );
  }
}
  1. 运行程序,如果程序正在运行可以选择热重载
    第一个Flutter APP

添加有状态部件(Stateful widget)

StatelessWidget是不可变的,以为着他们的属性不可变,StatefulWidget持有的状态可能在widget生命周期中发生变化实现一个StatefulWidget至少需要两个类:一个StatefulWidget类和一个State类
1. 在main.dart中创建RandomWords的widget

class RandomWords extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new RandomWordsState();
  }
}
  1. 添加RandomWidgetState类,该类持有RandomWord的状态
class RandomWordsState extends State<RandomWords> {
  @override
  Widget build(BuildContext context) {
    final wordPair = new WordPair.random();
    return new Text(wordPair.asPascalCase);
  }
}
  1. 然后来改造一下之前的代码
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @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.asPascalCase),
        child: new RandomWords(),
        ),
      ),
    );
  }
}
  1. 启动应用,观看效果
    第一个Flutter APP

创建一个ListView

  1. 在RandomWordsState类中添加_suggestions列表保存单词对,在Dart语言中使用下划线前缀表示变量,会强制变成私有,另外添加一个binggerFont变量来增大字体
class RandomWordsState extends State<RandomWords> {
  final _suggestions=<WordPair>[];
  final _biggerFont=const TextStyle(fontSize: 18.0);
}
  1. 在RandomWordsState类中添加_buildSuggestions方法,用来构建ListView
//构建ListView
Widget _buildSuggestions() {
    return new ListView.builder(
        padding: const EdgeInsets.all(16.0),
        // 在偶数行,该函数会为单词对添加一个ListTile row.
      // 在奇数行,该行书湖添加一个分割线widget,来分隔相邻的词对。
        itemBuilder: (context, i) {
          if (i.isOdd) {
            return new Divider();
          }
          final index = i ~/ 2;
          if (index >= _suggestions.length) {
            _suggestions.addAll(generateWordPairs().take(10));
          }
          return _buildRow(_suggestions[index]);
        });
  }
  1. 通过_buildRow方法构建一个条目
//构建条目
  Widget _buildRow(WordPair wordPair) {
    return new ListTile(
      title: new Text(
        wordPair.asPascalCase,
        style: _biggerFont,
      ),
    );
  }

4.更新RandomWordsState中的build方法

@override
  Widget build(BuildContext context) {
    //final wordPair = new WordPair.random();
    //return new Text(wordPair.asPascalCase);
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Startup Name Generator"),
      ),
      body: _buildSuggestions(),
    );
  }

5.更新MyApp的build方法,控件交由RandomWrodsState管理

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
//    final wordPair = new WordPair.random();
    return new MaterialApp(
      title: 'Welcome to Flutter',
      home: new RandomWords(),
    );
  }
}

6.重载应用,查看效果
第一个Flutter APP

增加交互

为每一个条目增加收藏功能
1. 在RandomWordsState中新增一个_saved集合

final _saved=new Set<WordPair>();
  1. 在_buildRow中添加一个心形图标以启用收藏功能
Widget _buildRow(WordPair wordPair) {
    final saved = _saved.contains(wordPair);
    return new ListTile(
      title: new Text(
        wordPair.asPascalCase,
        style: _biggerFont,
      ),
      trailing: new Icon(
        saved ? Icons.favorite : Icons.favorite_border,
        color: saved ? Colors.red : null,
      ),
    );
  }
  1. 给心形图标设置点击事件,图标被点击时调用setState()通知框架状态已经改变
 Widget _buildRow(WordPair wordPair) {
    final saved = _saved.contains(wordPair);
    return new ListTile(
      title: new Text(
        wordPair.asPascalCase,
        style: _biggerFont,
      ),
      trailing: new Icon(
        saved ? Icons.favorite : Icons.favorite_border,
        color: saved ? Colors.red : null,
      ),
      onTap: (){
        setState(() {
          if(saved){
            _saved.remove(wordPair);
          }else{
            _saved.add(wordPair);
          }
        });
      },
    );
  }

第一个Flutter APP

导航到新页面

在Flutter中,导航器管理应用程序的路由栈,将路由推入到导航器的栈中,将会显示更新为该路由界面。从导航器的栈中弹出路由,将显示返回到前一个路由

  1. 在RandomWordsState的build方法中为AppBar添加一个列表图标,当用户点击图标时,进入收藏夹页面
@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: _pushSaved)
        ],
      ),
      body: _buildSuggestions(),
    );
  }
  1. 当用户点击导航栏中的列表图标时,建立一个路由并推入到导航器管理栈中。新页面的内容在MaterialPageRoute的build属性中构建。
 void _pushSaved() {
    Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
      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 APP

更改UI主题

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Welcome to Flutter',
      theme: new ThemeData(
        primaryColor: Colors.white,
      ),
      home: new RandomWords(),
    );
  }
}

第一个Flutter APP

项目源码