Flutter 模仿微信读书实现案例

前言:

各位同学大家好,有一段时间没有给大家更新博客了,最近使用flutter跨平台写了一个模仿微信读书app demo版本(模仿其中部分经典页面不是全部)觉得有几个点值得分享一下,趁着今天放假,就发文章分线给大家,那么废话不多说我们正式开始

效果图:

Screenrecorder-2020-09-12-13-41-20-726[00_00_00--00_00_20].gif

准备工作:

需要安装flutter的开发环境:大家可以去看看之前的教程:
1 win系统flutter开发环境安装教程: https://www.jianshu.com/p/152447bc8718
2 mac系统flutter开发环境安装教程:https://www.jianshu.com/p/bad2c35b41e3

具体实现:

QQ截图20200912135506.png
效果分析:
我们看到底部的tab和上面的卡片形成了联动我们点击下面的button 和滑动都可以联动,flutter中底部的tab切换我们都是用 bottomNavigationBar 组件来实现,但是要实现联动我们需要配合PageView 来实现:
我们看下 TabNavigator中的代码实现

import 'package:flutter/material.dart';
import 'content_pager.dart';
/*** 创建人:xuqing* 创建时间:2020年2月7日16:26:18**/class TabNavigator extends StatefulWidget {TabNavigator({Key key}) : super(key: key);@override_TabNavigatorState createState() {return _TabNavigatorState();}
}class _TabNavigatorState extends State {final _defaultColor=Colors.grey;  //未选中final _activeColor=Colors.blue;  //选中的颜色int  _currentIndex=0;final ContentPagerConteroller _contentPagerConteroller=new ContentPagerConteroller();@overridevoid initState() {super.initState();
}@overridevoid dispose() {super.dispose();}@overrideWidget build(BuildContext context) {// TODO: implement buildreturn Scaffold(body: Container(decoration: BoxDecoration(gradient: LinearGradient(colors: [Color(0xffedeef0),Color(0xffe6e7E9),],begin: Alignment.topCenter,end: Alignment.bottomCenter)),child: ContentPager(contentPagerConteroller: _contentPagerConteroller,onPageChanged: (int index){setState(() {_currentIndex=index;});},)),bottomNavigationBar: BottomNavigationBar(items: [_bottomItem("本周", Icons.folder, 0),_bottomItem("分享", Icons.explore, 1),_bottomItem("免费", Icons.donut_small, 2),_bottomItem("长按", Icons.person, 3),],type: BottomNavigationBarType.fixed,currentIndex: _currentIndex,onTap: (index){_contentPagerConteroller.jumpTopage(index);setState(() {_currentIndex=index;});},),);}//封装底部的tab_bottomItem(String title, IconData icon ,int index){return BottomNavigationBarItem(icon: Icon(icon,color: _defaultColor,),activeIcon: Icon(icon,color: _activeColor,),title: Text(title,style:TextStyle(color:_currentIndex!=index?_defaultColor:_activeColor) ,));}
}

TabNavigator 里面我们通过 Decoration 设置背景渐变颜色,然后通过 bottomNavigationBar 设置底部的tab导航 切换的效果,TabNavigator 中整个布局我们上面一部分是一个ContentPager ()的widget
然后底部是一个 bottomNavigationBar 组件构成

ContentPager中具体里面的实现

ContentPager类中我们主要使用了 PageView 组件 来装在我们要显示的四个widget页面

Column(children: [CustomAppbar(),Expanded(child: PageView(onPageChanged: widget.onPageChanged,controller: _pageController,children: [_wrapItem(CardRecommend()),_wrapItem(CardShare()),_wrapItem(CardFree()),_wrapItem(CardSpecial()),],),)],);

然后我们在PageView 的 controller属性中设置显示比例:
这里我们设置为0.8就呈现我们想要的卡片的效果 要是们设置成1的话就撑满屏幕宽高这个要看你具求了
封装 _wrapItem 方法根据下标index来返回对应的Widget

 controller: _pageController,//视图比例PageController _pageController=PageController(viewportFraction: 0.8,);

封装 _wrapItem 方法根据下标index来返回对应的Widget

  Widget   _wrapItem(Widget widget){return  Padding(padding: EdgeInsets.all(10.0),child: widget);}

定义两个成员变量 onPageChanged contentPagerConteroller 用来回调给 TabNavigator

  final ValueChangedonPageChanged;final ContentPagerConteroller contentPagerConteroller;

onPageChanged 用来控制 滑动跟tab联动
contentPagerConteroller 用来控制点击底部的tab上的卡片Widget 切换
具体调用onPageChanged 调用

child: ContentPager(contentPagerConteroller: _contentPagerConteroller,onPageChanged: (int index){setState(() {_currentIndex=index;});},)

ContentPagerConteroller 类中小技巧

class ContentPagerConteroller{PageController _pageController;void  jumpTopage(int page){//dart 编程技巧 安全调用_pageController?.jumpToPage(page);}
}

这个样我们这个tab切换和联通效果我们就试下了
ContentPager完整代码

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'custom_appbar.dart';
import 'card_recommend.dart';
import 'card_share.dart';
import 'care_free.dart';
import 'card_special.dart';class ContentPager extends StatefulWidget {final ValueChangedonPageChanged;final ContentPagerConteroller contentPagerConteroller;//构造方法 可选参数ContentPager({Key key, this.onPageChanged, this.contentPagerConteroller}) : super(key: key);@override_ContentPagerState createState() {return _ContentPagerState();}
}
class _ContentPagerState extends State {//视图比例PageController _pageController=PageController(viewportFraction: 0.8,);static List_colorlist=[Colors.blue,Colors.red,Colors.deepOrange,Colors.teal,];@overridevoid initState() {// TODO: implement initStateif(widget.contentPagerConteroller!=null){widget.contentPagerConteroller._pageController=_pageController;}_statusBar();super.initState();}@overrideWidget build(BuildContext context) {// TODO: implement buildreturn Column(children: [CustomAppbar(),Expanded(child: PageView(onPageChanged: widget.onPageChanged,controller: _pageController,children: [_wrapItem(CardRecommend()),_wrapItem(CardShare()),_wrapItem(CardFree()),_wrapItem(CardSpecial()),],),)],);}Widget   _wrapItem(Widget widget){return  Padding(padding: EdgeInsets.all(10.0),child: widget);}_statusBar(){SystemUiOverlayStyle  uiOverlayStyle=SystemUiOverlayStyle(systemNavigationBarColor: Color(0xFF000000),systemNavigationBarDividerColor: null,statusBarColor: Colors.transparent,systemNavigationBarIconBrightness: Brightness.light,statusBarIconBrightness: Brightness.dark,statusBarBrightness: Brightness.light,);SystemChrome.setSystemUIOverlayStyle(uiOverlayStyle);}
}class  ContentPagerConteroller{PageController _pageController;void  jumpTopage(int page){//dart 编程技巧 安全调用_pageController?.jumpToPage(page);}
}

顶部appbar的实现 :

我这边是自定义了一个 widget实现的:
布局不难我们写了一个 Container 盒子组件然后里面嵌套Row组件的实现的

import 'package:flutter/material.dart';
/****  创建人 :xuqing*  创建时间:2020年2月9日15:53:54*  类说明:自定义appbar***/
class CustomAppbar extends StatefulWidget {CustomAppbar({Key key}) : super(key: key);@override_CustomAppbarState createState() {return _CustomAppbarState();}
}
class _CustomAppbarState extends State {@overridevoid initState() {super.initState();}@overridevoid dispose() {super.dispose();}@overrideWidget build(BuildContext context) {// TODO: implement builddouble paddingtop=MediaQuery.of(context).padding.top;return Container(margin: EdgeInsets.fromLTRB(20, paddingtop+10, 20, 5),padding: EdgeInsets.fromLTRB(20, 30, 20, 5),decoration: BoxDecoration(borderRadius: BorderRadius.circular(19),color: Colors.white60),child: Row(children: [Icon(Icons.search,color: Colors.grey,),Expanded(child: Text("长安十二实诚",style:TextStyle(fontSize: 15,color: Colors.grey),),),Container(width: 1,height: 20,margin: EdgeInsets.only(right: 13),decoration: BoxDecoration(color: Colors.grey),),Text("书城",style: TextStyle(fontSize: 13,),)],),);}
}

具体卡片页面的实现:

效果图:
QQ截图20200912143056.png
QQ截图20200912143139.png
我们分写发现正面这部分基本是重复出现的于是我们就写了一个 BaseCared这样一个基类来封装上面重复的组件

import 'package:flutter/material.dart';/****  创建人:xuqing*  创建时间:2020年2月12日23:10:48*  类说明:卡片基类****/class BaseCared extends StatefulWidget {BaseCared({Key key}) : super(key: key);@overrideBaseCaredState createState() {return BaseCaredState();}
}
class BaseCaredState extends State {Color subTitleColor=Colors.grey;Color bottomTitleColor=Colors.grey;@overridevoid initState() {super.initState();}@overridevoid dispose() {super.dispose();}@overrideWidget build(BuildContext context) {// TODO: implement buildreturn PhysicalModel(color: Colors.transparent,borderRadius: BorderRadius.circular(6),clipBehavior: Clip.antiAlias,child: Container(decoration: BoxDecoration(color: Colors.white),child: Column(children: [topContent(),bottomContent()],),),);}topContent(){return Padding(padding: EdgeInsets.only(left: 20,top: 26,bottom: 20),child: Column(crossAxisAlignment: CrossAxisAlignment.start,children: [Row(crossAxisAlignment: CrossAxisAlignment.end,children: [topTitle(""),topTtile2(),],),subTitle(""),],),);}bottomContent(){return Container();}Widget subTitle(String str){return Padding(padding: EdgeInsets.only(top: 5),child: Text(str,style: TextStyle(fontSize: 11,color: subTitleColor),),);}topTitle(String title){return Text(title,style: TextStyle(fontSize: 22),);}topTtile2( ){return Container();}bottomTitle(String title){return Text(title,style: TextStyle(fontSize: 11,color: bottomTitleColor),textAlign: TextAlign.center,);}
}

我们在BaseCared 类中分别定义了 subTitle topTitle topTtile2 bottomTitle 等方法让其他集成BaseCared 基类的组件类来重写调用
具体调用

 @overridetopTitle(String title) {// TODO: implement topTitlereturn super.topTitle("本周推荐");}@overrideWidget subTitle(String str) {// TODO: implement subTitlereturn super.subTitle("送你一张无限卡.全场数据免费读");}

由于篇幅问题各个卡片页面的具体实现我就不展开讲了有兴趣的朋友可以下载完整的代码参考,重点是BaseCared 基类封装的技巧和pageview 滑动联动的实现技巧,到此我们的flutter模仿微信读书app的案例就讲完了

最后总结:

这个模仿微信读书app项目并不难 但是其中巧妙的运用了一些dart 语言编程技巧和一些组件的配合使用
我觉得有必要分享给大家 ,大家如果觉得文章还不错麻烦给我一个star 和转发(我也是一名90后程序员)小弟在这里谢过啦 也可以加我个人QQ/微信(1693891473)

项目地址:

码云:https://gitee.com/qiuyu123/flutter_wechatredbook

QQ交流群:92437359.png


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部