Flutter实战之独立实现官网Demo单词收藏Demo

概述

这是一次独立尝试,即独立完成实现Flutter文档第一个项目的最终效果,实现目标即首页为一个可无限滚动的单词列表,点击单词右边的小心心即可收藏或者取消收藏,可以在右上角的列表页查看收藏的单词,自己实现的效果如下: 首页:

单词收藏页:

实现思路

看到这样一个功能,即可以分为两个页面,第一个页面本质就是一个列表页,每个列表分为两部分,即单词和收藏按钮,而第二个页面只需要显示单词,布局简单拆解:

接下我们就可以动手实践了,第一步添加需要用到的单词包
english_words,即在pubspec.yaml 中,将 english_words(3.1.0或更高版本)添加到依赖项列表:

dependencies:            
flutter:            
  sdk: flutter            
  cupertino_icons: ^0.1.2            
  english_words: ^3.1.0
复制代码

构建首页:

构建首页的appBar,同时注册第二个页面的路由和跳转按钮,以及定制一个简易棕色主题

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      // 去掉右上角的debug标识
      debugShowCheckedModeBanner: false,
      title: 'First Flutter',
      // 为第二个页面注册路由
      routes: {
        'love_page': (context) => LovePage(),
      },
      theme: ThemeData(
        primaryColor: Colors.grey,
      ),
      home: HomePage(),
    );
  }
}

// 首页
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: AppBar(
          title: Text('Words List'),
          actions: <Widget>[
            IconButton(
              // 第二个页面跳转按钮
              icon: Icon(Icons.list),
              onPressed: () {
                Navigator.pushNamed(context, 'love_page');
              },
            ),
          ],
        ),
        // 单词列表页面
        body: RandomWords());
  }
}
复制代码

构建单词列表及样式制定

构建一个单词列表,并定制列表单行(Container)的样式,比如背景white-black渐变效果,单词(child)字体大小及颜色,单词和按钮的布局,比如利用Expanded实现空白部分的扩充,使得“小心心”按钮靠右,利用ListView实现一个无线懒加载的单词列表等


// 单词列表页
class RandomWords extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new ListView.builder(
      itemBuilder: (BuildContext context, int index) {
        final _wordPair = WordPair.random();
        // 单个单词行的定制,包括一个单词和一个小心心按钮
        return Container(
            padding: EdgeInsets.symmetric(horizontal: 10),
            decoration: BoxDecoration(
                // 制作一个下边框作为每行的分割线
                border: Border(
                    bottom: BorderSide(
                        color: Colors.black26, style: BorderStyle.solid)),
                // 背景颜色渐变
                gradient:
                    LinearGradient(colors: [Colors.white30, Colors.black12])),
            height: 40,
            child: Row(
              children: <Widget>[
                Expanded(
                    flex: 5,
                    child: Text('$_wordPair',
                        style: TextStyle(color: Colors.brown, fontSize: 30))),
                Expanded(flex: 2, child: LoveWords(word: _wordPair)),
              ],
            ));
      },
    );
  }
}
复制代码

收藏’小心心’按钮实现

由于收藏点击小心心是个状态变化的过程,所以该小部件使用StatefulWidget 定义,同时传递一个全局变量存储收藏的单词便于传递给第二个单词收藏页面显示,该按钮部件实现点击小心心时改变小心心颜色为红色同时存储点击行的单词,或者“取消收藏”

// 收藏“小心心”按钮实现
class LoveWords extends StatefulWidget {
  LoveWords({Key key, this.word}) : super(key: key);
  // 怎么获取当列的数据
  final word;
  @override
  LoveWordsState createState() => new LoveWordsState();
}

// 全局变量存储 喜欢的单词 列表
var _loveList = <WordPair>[];

class LoveWordsState extends State<LoveWords> {
  var _colors = Colors.brown[170];
  var _icons = Icons.favorite_border;
  @override
  Widget build(BuildContext context) {
    return new IconButton(
      icon: Icon(_icons, size: 30, color: _colors),
      onPressed: () {
        setState(() {
          var word = widget.word;
          if (_colors == Colors.brown[170]) {
            _colors = Colors.red;
            _icons = Icons.favorite;
            // 使用widget.word。
            _loveList.add(word);
          } else {
            _colors = Colors.brown[170];
            _icons = Icons.favorite_border;
            _loveList.remove(word);
          }
        });
      },
    );
  }
}
复制代码

第二个页面: 单词收藏页面的实现

即显示收藏的单词,这里同样适用ListView展示收藏的单词列表,但是提前计算了收藏单词的数量限制了列表的大小,从而防止列表溢出。

// 显示喜欢的单词列表 页面
class LovePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: AppBar(title: Text('Favorite Words')),
      body: ListView.builder(
        // 限制列表数量
        itemCount: _loveList.length,
        itemBuilder: (BuildContext context, int index) {
            return new Container(
                padding: EdgeInsets.symmetric(horizontal: 10),
                decoration: BoxDecoration(
                    border: Border(
                        bottom: BorderSide(
                            color: Colors.black26, style: BorderStyle.solid)),
                    gradient: LinearGradient(
                        colors: [Colors.white30, Colors.black12])),
                height: 40,
                child: Row(
                  children: <Widget>[
                    Expanded(
                        flex: 5,
                        child: Text(_loveList[index].toString(),
                            style:
                                TextStyle(color: Colors.brown, fontSize: 30))),
                  ],
                ));
        },
      ),
    );
  }
}

复制代码

Summary

虽然实现效果和官网大致相似,但是实现代码和思路都大相径庭,可以看出官网实现的Demo对Widgets的利用确实精湛,值得深入学习! 完整代码:github.com/kavener/Flu…

转载于:https://juejin.im/post/5cc1b42c6fb9a0320a628ac8

    原文作者:weixin_34161029
    原文地址: https://blog.csdn.net/weixin_34161029/article/details/91481841
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞