带你Flutter带你Fly之单词收藏

本次笔者将实现这样一个效果:收藏列表的单词。并可点击页面右上角按钮展示收藏的单词

收藏个别单词.png

准备工作

打开Vs Code编辑器,快捷键 Crtl+Shift+P 打开 Commadn Palette命令板,输入 >Flutter:New Project 新建一个Flutter应用

输入应用名后,保存文件后,项目会自动进行创建,创建完毕之后,main.dart 文件会被自动打开。接下来,我们就对这个 main.dart 进行修改

一、熟悉 main.dart

把main.dart默认的代码替换成如下代码,建议手动敲打

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: "First Flutter App",
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text("My First Flutter App "),
        ),
        body: new Center(
          child: new Text("This is my first flutter app"),
        ),
      ),
    );
  }
}

打开模拟器或者真机,按F5,运行代码

1.png

代码还是比较简单的,主要有如下几个知识点:

  • main 方法采用了胖箭头 ( => ) 表示法,这是一种用于单行函数或方法的简写。
  • 该app继承了使它本身成为一个 widget 的 StatelessWidget 类。在 Flutter 中,大多数时候一切都可以看作 widget , 包括 alignment,padding 和 layout
  • Material 库中的 Scaffold widget 提供了默认的应用栏 (app bar),标题和构成主页面 widget 树结构的 body 属性
  • widget 的主要工作是提供一个build()方法,描述如何根据其他更低层级的 widget,来对这个 widget 进行展示
  • widget 树由包含了 Text child widget 的 Center widget 组成。Center widget 可将它的所有子树对齐到屏幕中心
二、使用外部package

这一步我们学习引入外部的package来随机生成一对英文单词。借助名为 english_words的开源软件包,它包含数千个最常用的英文单词以及一些实用功能

1.在 pubspec.yaml 文件中, 将 english_words(3.1.0或更高版本)添加到依赖列表

添加依赖库.png

2.Crtl+S 保存后它会自动将包拉入到项目中。或者直接控制台输入命令 flutter packages get

代码中导入该库

import 'package:english_words/english_words.dart';

更改一下代码,重新启动应用,这个时候会通过热重载的方式加载,速度很快,这个感觉是很爽的。

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

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

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    final wordpair=new WordPair.random();  //随机生成一对单词
    return new MaterialApp(
      title: "first flutter app",
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text("My First Flutter App "),
        ),
        body: new Center(
          //child: new Text("This is my first flutter app"),
          child: new Text(wordpair.asCamelCase),   //驼峰方式命名随机生成的单词
        ),
      ),
    );
  }
}

first app.png

三、添加有状态的widget

在前面的代码中, MyApp 类继承的是 StatelessWidget 类。但Stateless widgets是不可改变的,这意味着它们的属性不能改变,所有的值都是 final 的

实现一个有状态的 widget 至少需要两个类:StatefulWidgets类和State类,其中StatefulWidgets类创建了一个State类的实例。StatefulWidget类本身是不可变的,但State类可存在于Widget的整个生命周期中

1.创建一个 RandomWords widget。除了创建 State 类之外几乎没有任何其他代码

class RandomWords extends StatefulWidget{
  @override
  State<StatefulWidget> createState() => new RandomWordsState();
  }
  1. 创建 RandomWordsState 类。这个类保存了 RandomWords widget 的状态,该应用程序的大部分代码都放在该类的 build 方法中。
class RandomWordsState extends State<RandomWords>{
  @override
  Widget build(BuildContext context) {
    final wordPair=new WordPair.random();
    return new Text(wordPair.asCamelCase);
  }

3.修改 MyApp 中代码,重新启动应用,热重载后,效果和上图一样

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    //final wordpair=new WordPair.random();  //随机生成一对单词
    return new MaterialApp(
      title: "first flutter app",
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text("My First Flutter App "),
        ),
        body: new Center(
          //child: new Text("This is my first flutter app"),
         // child: new Text(wordpair.asCamelCase),   //驼峰方式命名随机生成的单词
         child: new RandomWords(),        //直接调用自定义的 RandomWords widget
        ),
      ),
    );
  }
}
四、创建一个ListView展示英文单词

生成并展示词组列表,需要扩展 RandomWordsState 类。当用户滑动列表,ListView widget 中显示的列表将无限增长。 ListView 的 builder 工厂构造函数允许按需建立一个延迟加载的列表 view。

1.准备一个数组用来存储随机生成的单词

class RandomWordsState extends State<RandomWords>{
    var _suggestWords = <WordPair>[];  //下划线表示私有
    //字体大小
    final _biggerFont = const TextStyle(fontSize: 18.0);
}
  1. 向 RandomWordsState 类添加一个_buildSuggestionWords() 方法,用于构建一个显示词组的 ListView。并调用 _buildRow 方法将每一个单词放入ListView的对应的item上
Widget _buildSuggestionWords(){
    return new ListView.builder(
      padding: const EdgeInsets.all(16.0),

      itemBuilder: (context,i){
        if(i.isOdd) return new Divider(); //listview的条目是奇数,画一条分割线

        final index = i ~/2;  // ~/ 表示除的结果取整

        if(index >= _suggestWords.length){ 
            _suggestWords.addAll(generateWordPairs().take(10));  //生成10个单词放入数组中
        }
         return _buildRow(_suggestWords[index]);
               },
            );
    }
  1. _buildRow 方法每次会在一个 ListTile widget中展示一条新词组
  Widget _buildRow(WordPair suggestWord) {
      return new ListTile(
        title: new Text(suggestWord.asPascalCase,
        style: _biggerFont,
        ),  
      );
    }

4.更新 RandomWordsState 类的 build 方法来使用 _buildSuggestions() 函数,而不是直接调用单词生成库

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Generate English Words"),
      ),
      body: _buildSuggestionWords(),
    );
  }

5.更新 MyApp 类的 build 方法,使用 RandomWords widget 来生成一个不断滚动的listview

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    //final wordpair=new WordPair.random();  //随机生成一对单词
    return new MaterialApp(
      title: "first flutter app",
      home: new RandomWords(),
    );
  }
}

未收藏.png

五、点击爱心收藏

为每一行添加可点击的心形图标。当用户点击列表中的条目,切换其“收藏”状态,词组就会添加到收藏栏,或从已保存词组的收藏栏中删除。

1.添加一个 Set 集合 _saved 到 RandomWordsState 类。保存用户收藏的词组。Set 集合比 List 更适用于此,因为它不允许重复元素。

2.在 _buildRow 函数中,添加 alreadySaved 标志检查来确保一个词组还没有被添加到收藏,并添加一个心形图标来使用收藏功能

Widget _buildRow(WordPair suggestWord) {
      final alreadySaved = _saved.contains(suggestWord);

      return new ListTile(
        title: new Text(suggestWord.asPascalCase,
        style: _biggerFont,
        ),  
        trailing: new Icon(//根据单词是否收藏决定是否点亮爱心
          alreadySaved ? Icons.favorite : Icons.favorite_border,
          color: alreadySaved ? Colors.red : null,
      )
      );
    }

3.虽然上面出现了心形图标,但还没有交互功能。在 _buildRow 函数中使心形可点击。如果词条已经被加入收藏,再次点击它将从收藏中删除

 Widget _buildRow(WordPair suggestWord) {
      final alreadySaved = _saved.contains(suggestWord);

      return new ListTile(
        title: new Text(suggestWord.asPascalCase,
        style: _biggerFont,
        ),  
        trailing: new Icon(   //根据单词是否收藏决定是否点亮爱心
          alreadySaved ? Icons.favorite : Icons.favorite_border,
          color: alreadySaved ? Colors.red : null,
      ),
        onTap: (){  //点击每个条目进行收藏单词和取消收藏
          setState(() {
                      if(alreadySaved)
                        _saved.remove(suggestWord);
                      else
                        _saved.add(suggestWord);
                    });
        } ,
      );
    }

在 Flutter 的响应式风格框架中,调用 setState() ,将为 State 对象触发 build() 方法的调用,从而实现对UI的更新。

收藏个别单词.png

六、跳转到收藏页面

添加一个显示收藏夹的新页面(在 Flutter 中称为 route(路由))。在 Flutter 中, Navigator 管理着包含了应用程序所有路由的一个堆栈。将一个路由push到 Navigator 的堆栈,将显示更新为新页面路由。将一个路由 pull 出 Navigator 的堆栈,显示将返回到前一个页面路由。

1.在 RandomWordsState 类的 build 方法中,向 AppBar 添加一个列表图标。当用户点击列表图标时,跳转到收藏的页面

 @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Generate English Words"),
        actions: <Widget>[
          //添加列表图标按钮,按下将调用_pushSaved 方法
          new IconButton(icon: new Icon(Icons.format_list_bulleted),onPressed: _pushSaved),  
        ],
      ),
      body: _buildSuggestionWords(),

    );
  }

2.向 RandomWordsState 类添加一个 _pushSaved() 方法,这个方法用于跳转到收藏单词的页面

  void _pushSaved(){
    //跳转到新的页面
    Navigator.of(context).push(  //函数调用添加到 Navigator.push 中作为参数,如高亮代码所示,将路由 push 到 Navigator 的堆栈中。
      new MaterialPageRoute(
        builder: (context){

          //把喜爱的单词放入listview的item中
          final tiles=_saved.map(
            (pair){
            return new ListTile(
              title: new Text(pair.asPascalCase,
              style: _biggerFont,
            ),
          );
        },
    );

   //为每个 ListTile widget 之间添加水平间距。divided变量保存最终生成的所有行,并用 toList() 函数转换为列表。
      final divided = ListTile.divideTiles(
        context: context,
        tiles: tiles,
      ).toList();

      //新的页面,新页面的body属性由包含多个 ListTile widget 的 ListView 组成。
      return new Scaffold(
        appBar: new AppBar(
           title: new Text('Favorite Words')),
           body: new ListView(children: divided),
      );

      },
    ),
  );
}
}

展示收藏单词.png

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值