Flutter入门(4):编写Flutter程序

1. 编写 Flutter 程序

下文是按照官方文档随便体验一下,有兴趣直接开始Flutter编程的可以点这里

2. 创建 flutter App

创建一个flutter App,可以参考创建流程

3. 运行 App

flutter run

4. 编辑第一个 Hello world程序

删除 main.dart 文件内容,复制粘贴以下代码,保存后刷新模拟器,可以参考flutter基本操作

import 'package:flutter/material.dart';

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

class MyApp 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('Hello World'),
        ),
      ),
    );
  }
}

5. 使用 Package

导入english_words的开源软件包 ,其中包含数千个最常用的英文单词以及一些实用功能.
首先打开App目录下 pubspec.yaml 文件,在 dependencies 下新增 english_words

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^0.1.0
  english_words: ^3.1.0

保存后,运行以下命令安装

flutter pub get

安装完成后,重新启动模拟器

flutter run

在 main.dart 文件中导入头文件,并修改部分代码,如下

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
        final wordPair = new WordPair.random();
        return new MaterialApp (
            title : 'Welcome',
            home : new Scaffold(
                appBar: new AppBar( title: new Text('Welcome to Flutter') ), 
                body : new Center(child: new Text(wordPair.asPascalCase)),
            ),
        );
    }
}

保存后,刷新模拟器


simulator.png

6. 添加一个 Stateful widget (标记状态的组件)

复制粘贴以下代码至 main.dart ,具体组件功能后续文章再做讲解。
运行后与之前效果完全相同,只不过是将 Text(wordPair.asPascalCase) 生成的随机单词换成 RandomWords() 生成的随机单词。

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
        return new MaterialApp (
            title : 'Welcome',
            home : new Scaffold(
                appBar: new AppBar( title: new Text('Welcome to Flutter') ), 
                body : new Center(child: new RandomWords()),
            ),
        );
    }
}

class RandomWords extends StatefulWidget {
    @override
    createState() => new RandomWordsState();
}

class RandomWordsState extends State <RandomWords> {
    @override
    Widget build(BuildContext context) {
        final wordPair = new WordPair.random();
        return new Text(wordPair.asPascalCase);
    }
}

7. 创建一个 ListView (TableView)

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
        return new MaterialApp (
            title : 'Welcome',
            home : new RandomWords(),
        );
    }
}

class RandomWords extends StatefulWidget {
    @override
    createState() => new RandomWordsState();
}

class RandomWordsState extends State <RandomWords> {
    @override
    final _suggestions = <WordPair>[];
    final _biggerFont = const TextStyle(fontSize : 18.0);
    Widget build(BuildContext context) {
        return new Scaffold(
            appBar: new AppBar(title: new Text('ListView')),
            body: _buildSuggestions(),
            );
    }
    Widget _buildSuggestions() {
        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 >= _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,
            )
        );
    }
}

运行后如下


simulator_listview.png

8. 添加 ListView 的点击事件,并对点击状态进行保存

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
        return new MaterialApp (
            title : 'Welcome',
            home : new RandomWords(),
        );
    }
}

class RandomWords extends StatefulWidget {
    @override
    createState() => new RandomWordsState();
}

class RandomWordsState extends State <RandomWords> {
    @override
    final _suggestions = <WordPair>[];
    final _saved = new Set<WordPair>();
    final _biggerFont = const TextStyle(fontSize : 18.0);
    Widget build(BuildContext context) {
        return new Scaffold(
            appBar: new AppBar(title: new Text('ListView')),
            body: _buildSuggestions(),
            );
    }
    Widget _buildSuggestions() {
        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 >= _suggestions.length) {
                    _suggestions.addAll(generateWordPairs().take(10));
                }
                return _buildRow(_suggestions[index]);
            }
        );
    }
    Widget _buildRow(WordPair pair) {
        final alreadySaved = _saved.contains(pair);
        return new ListTile(
            title : new Text(
                pair.asPascalCase,
                style: _biggerFont,
            ),
            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);
                    }
                });
            },
        );
    }
}

运行刷新后如下


simulator_state.png

9. 通过路由实现 flutter 的页面跳转

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
        return new MaterialApp (
            title : 'Welcome',
            home : new RandomWords(),
        );
    }
}

class RandomWords extends StatefulWidget {
    @override
    createState() => new RandomWordsState();
}

class RandomWordsState extends State <RandomWords> {
    @override
    final _suggestions = <WordPair>[];
    final _saved = new Set<WordPair>();
    final _biggerFont = const TextStyle(fontSize : 18.0);
    Widget build(BuildContext context) {
        return new Scaffold(
            appBar: new AppBar(title: new Text('ListView'),
                actions: <Widget>[
                new IconButton(icon: new Icon(Icons.list), onPressed: _pushSaved),
                ],
            ),
            body: _buildSuggestions(),
        );
    }
    Widget _buildSuggestions() {
        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 >= _suggestions.length) {
                    _suggestions.addAll(generateWordPairs().take(10));
                }
                return _buildRow(_suggestions[index]);
            }
        );
    }
    Widget _buildRow(WordPair pair) {
        final alreadySaved = _saved.contains(pair);
        return new ListTile(
            title : new Text(
                pair.asPascalCase,
                style: _biggerFont,
            ),
            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);
                    }
                });
            },
        );
    }
    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),
                    );
                },
            ),
        );
    }
}

保存运行后如图


simulator_route_home.png

simulator_route_push.png

10. 更改主题色

通过 ThemeData 类来改变主题色,修改以下部分代码

class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
        return new MaterialApp (
            title : 'Welcome',
            theme: new ThemeData(
                primaryColor: Colors.white,
            ),
            home : new RandomWords(),
        );
    }
}

保存运行后如下图


simulator_route_home_white.png

simulator_route_push_white.png

11. 小结

本文到这里就结束了,全部代码均为跟着官方教程走了一遍。主要就以下几个功能点

  • ListView 的创建
  • ListView 的Item状态及保存
  • Item 的状态保存及按照不同的状态刷新UI
  • Route 的页面跳转及回跳
  • 主题色的修改
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 227,663评论 6 531
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 98,125评论 3 414
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 175,506评论 0 373
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 62,614评论 1 307
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,402评论 6 404
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 54,934评论 1 321
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,021评论 3 440
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,168评论 0 287
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,690评论 1 333
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,596评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,784评论 1 369
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,288评论 5 357
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,027评论 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,404评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,662评论 1 280
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,398评论 3 390
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,743评论 2 370