为了账号安全,请及时绑定邮箱和手机立即绑定

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;
  
  LoveWordsState createState() => new LoveWordsState();
}

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

class LoveWordsState extends State<LoveWords> {
  var _colors = Colors.brown[170];
  var _icons = Icons.favorite_border;
  
  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 {
  
  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的利用确实精湛,值得深入学习!
完整代码:https://github.com/kavener/FlutterWidgets/blob/master/lib/FirstFlutter/MyApp.dart

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Python工程师
手记
粉丝
23
获赞与收藏
95

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消