原标题:Flutter 模仿微信读书效果!

作者:xq9527链接:https://www.jianshu.com/p/ee9d30ba2c42

前言

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

效果图

准备工作

需要安装flutter的开发环境:大家可以去看看之前的教程:

2、mac系统flutter开发环境安装教程:https://www.jianshu.com/p/bad2c35b41e3

具体实现

效果分析:

我们看到底部的tab和上面的卡片形成了联动,我们点击下面的button 和滑动都可以联动,flutter中底部的tab切换我们都是用 bottomNavigationBar 组件来实现,但是要实现联动我们需要配合PageView 来实现:

我们看下 TabNavigator中的代码实现

import'package:flutter/material.dart';

import'content_pager.dart';

/**

*创建人:xuqing

*创建时间:2020年2月7日16:26:18

*

*/

classTabNavigatorextendsStatefulWidget{

TabNavigator({Key key}) : super(key: key);

@override

_TabNavigatorState createState {

return_TabNavigatorState;

}

}

class_TabNavigatorStateextendsState< TabNavigator>{

final_defaultColor=Colors.grey; //未选中

final_activeColor=Colors.blue; //选中的颜色

int_currentIndex= 0;

finalContentPagerConteroller _contentPagerConteroller= newContentPagerConteroller;

@override

voidinitState {

super.initState;

}

@override

voiddispose {

super.dispose;

}

@override

Widget build(BuildContext context) {

// TODO:implement build

returnScaffold(

body: Container(

decoration: BoxDecoration(

gradient: LinearGradient(

colors: [

Color( 0xffedeef0),

Color( 0xffe6e7E9),

],

begin: Alignment.topCenter,

end: Alignment.bottomCenter

)

),

child: ContentPager(

contentPagerConteroller: _contentPagerConteroller,

onPageChanged: ( intindex){

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( Stringtitle, IconData icon , intindex){

returnBottomNavigationBarItem(

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 的话就撑满屏幕宽高,这个要看你具求了

controller: _pageController,

//视图比例

PageController _pageController=PageController(

viewportFraction: 0.8,

);

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

Widget _wrapItem(Widget widget){

returnPadding(padding: EdgeInsets.all( 10.0),

child: widget

);

}

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

finalValueChanged< int>onPageChanged;

finalContentPagerConteroller contentPagerConteroller;

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

具体调用onPageChanged 调用

child: ContentPager(

contentPagerConteroller: _contentPagerConteroller,

onPageChanged: ( intindex){

setState( {

_currentIndex=index;

});

},

)

ContentPagerConteroller 类中小技巧

classContentPagerConteroller{

PageController _pageController;

voidjumpTopage( intpage){

//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';

classContentPagerextendsStatefulWidget{

finalValueChanged< int>onPageChanged;

finalContentPagerConteroller contentPagerConteroller;

//构造方法 可选参数

ContentPager({Key key, this.onPageChanged, this.contentPagerConteroller}) : super(key: key);

@override

_ContentPagerState createState {

return_ContentPagerState;

}

}

class_ContentPagerStateextendsState< ContentPager>{

//视图比例

PageController _pageController=PageController(

viewportFraction: 0.8,

);

staticList_colorlist=[

Colors.blue,

Colors.red,

Colors.deepOrange,

Colors.teal,

];

@override

voidinitState {

// TODO:implement initState

if(widget.contentPagerConteroller!= null){

widget.contentPagerConteroller._pageController=_pageController;

}

_statusBar;

super.initState;

}

@override

Widget build(BuildContext context) {

// TODO:implement build

returnColumn(

children: [

CustomAppbar,

Expanded(

child: PageView(

onPageChanged: widget.onPageChanged,

controller: _pageController,

children: [

_wrapItem(CardRecommend),

_wrapItem(CardShare),

_wrapItem(CardFree),

_wrapItem(CardSpecial),

],

),

)

],

);

}

Widget _wrapItem(Widget widget){

returnPadding(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);

}

}

classContentPagerConteroller{

PageController _pageController;

voidjumpTopage( intpage){

//dart 编程技巧 安全调用

_pageController?.jumpToPage(page);

}

}

顶部appbar的实现

我这边是自定义了一个 widget实现的:

布局不难,我们写了一个 Container 盒子组件,然后里面嵌套Row组件实现的

import'package:flutter/material.dart';

/ ***

*创建人 :xuqing

*创建时间:2020年2月9日15:53:54

*类说明:自定义appbar

*

*

*/

classCustomAppbarextendsStatefulWidget{

CustomAppbar({Key key}) : super(key: key);

@override

_CustomAppbarState createState {

return_CustomAppbarState;

}

}

class_CustomAppbarStateextendsState< CustomAppbar>{

@override

voidinitState {

super.initState;

}

@override

voiddispose {

super.dispose;

}

@override

Widget build(BuildContext context) {

// TODO:implement build

doublepaddingtop=MediaQuery.of(context).padding.top;

returnContainer(

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,

),

)

],

),

);

}

}

具体卡片页面的实现:

我们分析发现正面这部分基本是重复出现的,于是我们就写了 BaseCared这样一个基类来封装上面重复的组件

import'package:flutter/material.dart';

/**

*

* 创建人:xuqing

*创建时间:2020年2月12日23:10:48

*类说明:卡片基类

*

*

*

*/

classBaseCaredextendsStatefulWidget{

BaseCared({Key key}) : super(key: key);

@override

BaseCaredState createState {

returnBaseCaredState;

}

}

classBaseCaredStateextendsState< BaseCared>{

Color subTitleColor=Colors.grey;

Color bottomTitleColor=Colors.grey;

@override

voidinitState {

super.initState;

}

@override

voiddispose {

super.dispose;

}

@override

Widget build(BuildContext context) {

// TODO:implement build

returnPhysicalModel(color: Colors.transparent,

borderRadius: BorderRadius.circular( 6),

clipBehavior: Clip.antiAlias,

child: Container(

decoration: BoxDecoration(color: Colors.white),

child: Column(

children: [

topContent,

bottomContent

],

),

),

);

}

topContent{

returnPadding(

padding: EdgeInsets.only(left: 20,top: 26,bottom: 20),

child: Column(

crossAxisAlignment: CrossAxisAlignment.start,

children: [

Row(

crossAxisAlignment: CrossAxisAlignment.end,

children: [

topTitle( ""),

topTtile2,

],

),

subTitle( ""),

],

),

);

}

bottomContent{

returnContainer;

}

Widget subTitle( Stringstr){

returnPadding(

padding: EdgeInsets.only(top: 5),

child: Text(

str,style: TextStyle(

fontSize: 11,

color: subTitleColor

),

),

);

}

topTitle( Stringtitle){

returnText(title,style: TextStyle(

fontSize: 22

),);

}

topTtile2( ){

returnContainer;

}

bottomTitle( Stringtitle){

returnText(title,style: TextStyle(

fontSize: 11,

color: bottomTitleColor

),

textAlign: TextAlign.center,

);

}

}

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

具体调用 @override

topTitle( Stringtitle) {

// TODO:implement topTitle

returnsuper.topTitle( "本周推荐");

}

@override

Widget subTitle( Stringstr) {

// TODO:implement subTitle

returnsuper.subTitle( "送你一张无限卡.全场数据免费读");

}

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

最后总结

这个模仿微信读书app项目并不难 但是其中巧妙的运用了一些dart 语言编程技巧和一些组件的配合使用

我觉得有必要分享给大家 ,大家如果觉得文章还不错麻烦给我一个star 和转发(我也是一名90后程序员)谢谢大家

项目地址:码云:https://gitee.com/qiuyu123/flutter_wechatredbook返回搜狐,查看更多

责任编辑:

flutter 微信语言选择_Flutter 模仿微信读书效果!相关推荐

  1. flutter 微信语言选择_Flutter/dart聊天实例|仿微信界面|红包|朋友圈

    FlutterChatroom项目是基于flutter+dart+image_picker等技术实现的仿微信app聊天室实战项目. 一.技术框架编码/技术:Vscode + Flutter 1.12. ...

  2. flutter 微信语言选择_Flutter 玩转微信——通讯录

    概述 鄙人于闲暇之日,自学Flutter已有两月之久,古人曰:百闻不如一见,百见不如一试,特此利用生平之所学,实战微信以项目.Flutter,学语法之轻易,用组件之简单,源码开源,插件丰富.然一份代码 ...

  3. flutter 微信语言选择_flutter实战项目,教你使用flutter打造微信app页面!

    flutter_wechat

  4. android 仿微信选取相册_Android模仿微信选择图片

    前言 最近公司需要做一个类似微信那种选择头像和上传图片的功能,本想上github上找的,后来想了想,还是自己做一个,不仅方便以后用(毕竟自己写的修改起来也比较方便),还可以学到一些知识,废话少说,先看 ...

  5. android 仿微信头像裁剪,android 模仿微信头像裁剪

    android 在android开发中经常会碰到修改头像的功能需求, 而在修改头像>中最难的部分就是在头像的裁剪功能.虽说网上一大堆裁剪的例子,但最重要的是要理解里面的实现原理,这样以后自己改起 ...

  6. android 微信启动动画,Android 模仿微信启动动画(转)

    本文内容 环境 项目结构 演示微信启动动画 本文演示微信启动动画.请点击此处下载,自行调试. 顺便抱怨一下,实践性(与研究性质的相对)技术博的"七宗罪": 第一宗罪,错字连篇,逻辑 ...

  7. flutter 微信语言选择_#Flutter项目(3)之仿写微信通讯录界面

    1 导航栏按钮的添加 导航栏 appBar 使用AppBar()方法创建:主要用到的控件属性如下: title:导航栏标题 /// The primary widget displayed in th ...

  8. android 微信图片选择,Android实现微信的图片选择器

    现在大部分的App都上传图片的功能,比如设置用户头像.聊天发送图片.发表动态.论坛帖子等.上传图片需要先从选择手机中选择要上传的图片,所以图片选择器在App中是很常见的组件,一般的手机都会自带一个图片 ...

  9. 微信朋友圈,模仿微信朋友圈,朋友圈点赞评论

    1.上图  2.上代码 <div class="base-wrap word-break" style="padding: 40px 0 100px;"& ...

最新文章

  1. 特征工程(一)countvectororizer
  2. OSPF多区域;特殊区域;
  3. MySQL数据库性能优化--SQL优化
  4. 【JAVA】大整数数据量排序
  5. 开源软件 许可证密钥_自由和开源软件-1中的重要许可证
  6. javascript 之作用域-06
  7. 三包围结构的字是什么样的_一年级语文重点(字、字母、字词、词语、句子)知识点汇总!...
  8. git完全cli指南之详细思维导图整理分享
  9. 悲观锁 HibernateTest.java
  10. dsoframer java_DSOFramer的使用
  11. spring boot + websocket 简单实现斗鱼弹幕功能
  12. 茶 与 茶道 之 人生如茶
  13. win10 Edge浏览器 触控板 快捷键
  14. mybatis 九大动态标签详解
  15. 游戏版权律师/软件律师的专业作用
  16. java 抓取 flash 控件,java-从Flash抓取数据(游戏)
  17. Power2Go 13安装教程
  18. 什么是文件目录,文件目录项的主要内容是什么?
  19. Matlab【特征提取】频带方差端点检测含Matlab源码
  20. 地图绘制边界。高德。PPMAP。 鼠标点击经纬度坐标 。地图图标点点击弹窗窗口。地图图标点点击事件。

热门文章

  1. 据说能答对5道题的人是天才,答对4道的是帅才,答对3道的是将才,答对2道的是奇才,答对1道的是人才...
  2. 晕死,咖啡.....以后不喝咖啡了.....
  3. sql server从插入数据到用游标操作数据库(2/3部分)--用心造
  4. 读书笔记-精准努力-出身寒门改变命运
  5. PHP开启magic扩展,php.ini中Magic_Quotes_Gpc开关设置
  6. mix2刷android p教程,小米MIX2Android P使用谷歌相机教程
  7. 最近在玩微博,觉得微博学习到了一点东西,分享下
  8. [league/climate]一个功能健全的命令行功能操作库
  9. 苹果 iOS 14.2 Beta 2发布!还是会闪退?
  10. nginx出现 “414 request-uri too large”