Flutter实战之实现一个简单的新闻阅读器

Flutter实战之实现一个简单的新闻阅读器纸上谈兵终觉浅,绝知此事要躬行。 catsao(音:cat骚),我撸的第一个Flutter Application Demo,目前阶段它主要仿造目前主流的新闻资讯类app布局,实现了简单的新闻浏览。我还要继续丰富它,让它越来越sao。 主要通过DefaultTabControl…

Introduction

纸上谈兵终觉浅,绝知此事要躬行。

catsao(音:cat骚),我撸的第一个Flutter Application Demo,目前阶段它主要仿造目前主流的新闻资讯类app布局,实现了简单的新闻浏览。我还要继续丰富它,让它越来越sao。

Points

  • TabBar实现:
 @override
 Widget build(BuildContext context) {
   final List<Text> tabTexts = <Text>[
     new Text(
         StringResources.TAB_TOP_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     ),
     new Text(
         StringResources.TAB_SH_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     ),
     new Text(
         StringResources.TAB_GN_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     ),
     new Text(
         StringResources.TAB_GJ_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     ),
     new Text(
         StringResources.TAB_YL_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     ),
     new Text(
         StringResources.TAB_TY_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     ),
     new Text(
         StringResources.TAB_JS_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     ),
     new Text(
         StringResources.TAB_KJ_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     ),
     new Text(
         StringResources.TAB_CJ_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     ),
     new Text(
         StringResources.TAB_SS_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     )
   ];
   final List<Tab> tabs = [];
   for (int i = 0 ; i < tabTexts.length ; i++) {
     tabs.add(
       new Tab(
         child: tabTexts[i],
       )
     );
   }

   return new DefaultTabController(
       length: tabs.length,
       child: new Scaffold(
         appBar: new AppBar(
           title: new Text(
               widget.title
           ),
           bottom: new TabBar(
             isScrollable: true,
             tabs: tabs,

           ),
         ),
         body: new TabBarView(
             children: tabTexts.map((Text tab) {
               return new Center(
                 child: new NewsPage(
                   tabName: tab.data,
                 )
               );
             }).toList()
         ),
         drawer: new DrawerPage(),
       )
   );
 }

主要通过DefaultTabController + TabBar + TabBarView三个Widget配合实现类似Android中ViewPager + Indicator的效果。

build方法返回的最外层是一个DefaultTabController Widget,正如它的名字那样,它是一个控制器,用来控制TabBar和TabBarView的联动。要在界面上绘制一个TabBar和其对应的内容页使用TabBar和TabBarView两个Widget来实现的。

通过配置Scaffold的appbar参数为界面添加一个标题栏,再配置AppBar的bottom参数为标题栏添加一个显示在其底部的Widget,在这里传递给bottom参数的是一个TabBar Widget,所以在标题栏下方会显示一个TabBar。TabBar的每个Tab默认是固定位置的,这里配置其isScrollable参数为true使其可滚动,tabs参数配置TabBar中的每个Tab Widget。

通过配置Scaffold的body参数为其添加主内容界面,这里的内容界面需要配合TabBar的切换而切换,所以配置一个TabBarView Widget。最终通过外层的DefaultTabController使得TabBar和TabBarView联动起来。

关于实现类似效果的更多详细信息可参阅DefaultTabControllerTabBarTabBarView

  • Drawer实现:
	return new DefaultTabController(
       length: tabs.length,
       child: new Scaffold(
         appBar: new AppBar(
           title: new Text(
               widget.title
           ),
           bottom: new TabBar(
             isScrollable: true,
             tabs: tabs,

           ),
         ),
         body: new TabBarView(
             children: tabTexts.map((Text tab) {
               return new Center(
                 child: new NewsPage(
                   tabName: tab.data,
                 )
               );
             }).toList()
         ),
         drawer: new DrawerPage(),
       )
   );

Drawer的实现也很简单,Flutter都已经封装好了,直接配置Scaffold的drawer参数来实现一个Drawer界面。

  • 数据缓存:

利用shared_preferences和sqflite插件分别实现SharePreference和DB的数据本地缓存,在项目的pubspec.yaml中配置依赖的插件:

dependencies:

  ......
  sqflite: "^0.8.3"
  shared_preferences: "^0.4.0"
  ......
  

然后就可以在使用的地方import相应的package来使用对应功能。

  • Column问题

使用Column时会遇到一个there are children with non-zero flex but the vertical constraints are unbounded的异常,大致意思是说Column内部有flex值不为0的children,但是当前Column在垂直方向的高度约束是无限制的。 简单解释一下,Column的children默认flex值是0,可以理解为flex为0的组件占用的空间是静态的。当一个组件的flex值不为0时,意味着它会去占用父容器布局完其他flex为0的组件后剩下的空间,占用多少跟flex的值有关。这有点类似Android中LinearLayout的weight。所以这个异常的意思其实是说因为当前的Column的垂直方向的高度约束是没有任何限制的,此时内部如果有flex非0的children的话它无法确定父容器的剩余空间有多大。

当一个Column的children中有一个或多个Expanded或Flexible组件,并且这个Column嵌套在另一个Column或ListView的内部,就会遇到这个问题。

解决的思路其实就是检查为什么自己的Column此时在垂直方向的高度约束是无限制的,大部分情况下可能是由于当前Column嵌套在另一个Column或ListView等容器中导致的。

关于该问题的详细描述可以参阅官方文档

Effect

Flutter实战之实现一个简单的新闻阅读器

Flutter实战之实现一个简单的新闻阅读器

Flutter实战之实现一个简单的新闻阅读器

由于聚合数据只有获取新闻列表的接口(也可能我没找到单条新闻详情的接口),所以目前点击新闻的跳转是直接用浏览器打开了其对应的url。另外聚合数据获取新闻列表的接口貌似也没有支持分页参数…我还升级了聚合数据的高级会员,略坑。

Todo

  • 下拉刷新
  • 增加不同频道Route
  • 图片本地缓存

End

天气接口:和风天气。

新闻接口:聚合数据。

部分图标:Iconfont-阿里巴巴矢量图标库。

源码地址:Catsao

关于Flutter项目的编译和运行可以参考官方文档

今天的文章Flutter实战之实现一个简单的新闻阅读器分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:http://bianchenghao.cn/22616.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注