09 Flutter底部Tab切换保持页面状态的几种方法
import 'package:flutter/material.dart'; import 'Home.dart';
import 'Cart.dart';
import 'Category.dart';
import 'User.dart'; class Tabs extends StatefulWidget {
Tabs({Key key}) : super(key: key); _TabsState createState() => _TabsState();
} class _TabsState extends State<Tabs> {
int _currentIndex = 1;
PageController _pageController;
void initState(){
super.initState();
this._pageController=new PageController(initialPage: this._currentIndex);
}
List<Widget> _pageList = [HomePage(), CategoryPage(), CartPage(), UserPage()];
@override
Widget build(BuildContext context) {
return Container(
child: Scaffold(
appBar: AppBar(
title: Text('jdshop'),
),
//页面状态保持第一种方法:
//保持所有的页面状态,使用indexedStack
// body:IndexedStack(
// index: this._currentIndex,
// children:_pageList
// ),
//保持部分页面的状态:
// body:PageView( //修改的部分:
controller: this._pageController,
children:this._pageList,
// onPageChanged(){ // },
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: this._currentIndex,
onTap: (index) {
this.setState(() {
this._currentIndex = index;
this._pageController.jumpToPage(this._currentIndex);
});
},
type: BottomNavigationBarType.fixed,
fixedColor: Colors.red,
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('首页')),
BottomNavigationBarItem(
icon: Icon(Icons.category), title: Text('分类')),
BottomNavigationBarItem(
icon: Icon(Icons.shopping_cart), title: Text('购物车')),
BottomNavigationBarItem(icon: Icon(Icons.people), title: Text('我的'))
],
),
),
);
}
}
Home.dart
import 'package:flutter/material.dart'; //热门推荐:
import '../../model/ProductModel.dart';
import 'package:flutter_swiper/flutter_swiper.dart';
// import 'dart:convert';
import '../../services/ScreenAdaper.dart';
import '../../config/Config.dart';
import 'package:dio/dio.dart';
//轮播图类模型:
import '../../model/FocusModel.dart'; class HomePage extends StatefulWidget {
HomePage({Key key}) : super(key: key); _HomePageState createState() => _HomePageState();
} class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin {
//轮播图:
//flutter run -d all 链接多个设备的命令:
List _focusData = [];
List _hotProductList=[];
List _bestProductList=[];
@override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
void initState() {
super.initState();
_getFocusData();
_getHotProductData();
_getBestProductData();
}
//获取轮播图数据:
_getFocusData() async {
var api = '${Config.domain}api/focus';
var result = await Dio().get(api);
var focusList = FocusModel.fromJson(result.data);
focusList.result.forEach((value) {
print(value.title);
print(value.pic);
});
setState(() {
this._focusData = focusList.result;
});
}
//获取猜你喜欢的数据:
_getHotProductData() async{
var api='${Config.domain}api/plist?is_hot=1';
var result=await Dio().get(api);
var hotProductList=ProductModel.fromJson(result.data);
setState(() {
this._hotProductList= hotProductList.result;
});
}
//获取热门推荐的数据:
_getBestProductData() async{
var api='${Config.domain}api/plist?is_best=1';
var result=await Dio().get(api);
var bestProductList=ProductModel.fromJson(result.data);
setState(() {
this._bestProductList= bestProductList.result;
});
} Widget _swiperWidget() {
// List<Map> imgList = [
// {"url": "https://www.itying.com/images/flutter/slide01.jpg"},
// {"url": "https://www.itying.com/images/flutter/slide02.jpg"},
// {"url": "https://www.itying.com/images/flutter/slide03.jpg"}
// ];
if (this._focusData.length > 0) {
return Container(
child: AspectRatio(
aspectRatio: 2 / 1,
child: Swiper(
itemBuilder: (BuildContext context, int index) {
String pic=this._focusData[index].pic;
pic=Config.domain+pic.replaceAll('\\', '/');
return new Image.network(
"${pic}",
fit: BoxFit.fill,
);
},
itemCount: this._focusData.length,
pagination: new SwiperPagination(),
control: new SwiperControl(),
autoplay: true,
),
),
);
} else {
return Text('加载中~');
}
} //标题:
Widget _titleWidget(value) {
return Container(
height: ScreenAdaper.height(46),
margin: EdgeInsets.only(left: ScreenAdaper.width(20)),
padding: EdgeInsets.only(left: ScreenAdaper.width(20)),
decoration: BoxDecoration(
border: Border(
left: BorderSide(
color: Colors.red, width: ScreenAdaper.width(10)))),
child: Text(value, style: TextStyle(color: Colors.black54)),
);
} //热门商品:
Widget _hotProductListWidget() {
if(this._hotProductList.length>0){
return Container(
height: ScreenAdaper.height(240),
padding: EdgeInsets.all(ScreenAdaper.width(20)),
// width: double.infinity, //寬度自適應
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemBuilder: (contxt, index) { String sPic=this._hotProductList[index].sPic;
sPic=Config.domain+sPic.replaceAll('\\', '/');
return Column(
children: <Widget>[
Container(
height: ScreenAdaper.height(140),
width: ScreenAdaper.width(140),
margin: EdgeInsets.only(right: ScreenAdaper.width(21)),
child: Image.network(
"${sPic}",
fit: BoxFit.cover),
),
Container(
padding: EdgeInsets.only(top: ScreenAdaper.height(10)),
height: ScreenAdaper.height(44),
child: Text(
"¥${this._hotProductList[index].price}",
style: TextStyle(color: Colors.red),
),
)
],
);
},
itemCount: this._hotProductList.length,
),
); }else{
return Text('暂无热门推荐数据');
} } Widget _recProductListWidget() { var itemWidth = (ScreenAdaper.getScreenWidth() - 30) / 2;
return Container(
padding: EdgeInsets.all(10),
child: Wrap(
runSpacing: 10,
spacing: 10,
children:this._bestProductList.map((value){
//图片:
var sPic=value.sPic;
sPic=Config.domain+sPic.replaceAll('\\','/'); return Container(
padding: EdgeInsets.all(ScreenAdaper.width(20)),
width: itemWidth,
decoration:
BoxDecoration(border: Border.all(color: Colors.black12, width: 1)),
child: Column(
children: <Widget>[
Container(
width: double.infinity,
child: AspectRatio(
aspectRatio: 1 / 1,
child: Image.network(
"${sPic}",
fit: BoxFit.cover),
),
),
Padding(
padding: EdgeInsets.only(top: ScreenAdaper.height(10)),
child: Text(
"${value.title}",
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(color: Colors.black54),
),
),
Padding(
padding: EdgeInsets.only(top: ScreenAdaper.height(20)),
child: Stack(
children: <Widget>[
Align(
alignment: Alignment.centerLeft,
child: Text(
"${value.price}",
style: TextStyle(color: Colors.red, fontSize: 16),
),
),
Align(
alignment: Alignment.centerRight,
child: Text(
"¥${value.oldPrice}",
style: TextStyle(
color: Colors.black54,
fontSize: 16,
decoration: TextDecoration.lineThrough),
),
)
],
),
)
],
),
); }).toList(),
),
); } @override
Widget build(BuildContext context) {
ScreenAdaper.init(context);
return ListView(
children: <Widget>[
_swiperWidget(),
SizedBox(height: ScreenAdaper.height(20)),
_titleWidget("猜你喜欢"),
_hotProductListWidget(),
SizedBox(height: ScreenAdaper.height(20)),
_titleWidget("热门推荐"),
_recProductListWidget()
],
);
}
}
Category.dart
import 'package:flutter/material.dart';
import '../../services/ScreenAdaper.dart';
import '../../config/Config.dart';
import 'package:dio/dio.dart';
import '../../model/CateModel.dart'; class CategoryPage extends StatefulWidget {
CategoryPage({Key key}) : super(key: key); _CategoryPageState createState() => _CategoryPageState();
} class _CategoryPageState extends State<CategoryPage> with AutomaticKeepAliveClientMixin{
int _selectIndex = 0;
List _leftCateList = [];
List _rightCateList = [];
@override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
@override
void initState() {
super.initState();
_getLeftCateData();
} //左侧数据:
_getLeftCateData() async {
var api = '${Config.domain}api/pcate';
var result = await Dio().get(api);
var leftCateList = CateModel.fromJson(result.data);
setState(() {
this._leftCateList = leftCateList.result;
});
_getRightCateData(leftCateList.result[0].sId);
} //右侧数据:
_getRightCateData(pid) async {
var api = '${Config.domain}api/pcate?pid=${pid}';
var result = await Dio().get(api);
var rightCateList = CateModel.fromJson(result.data);
setState(() {
this._rightCateList = rightCateList.result;
});
} //左侧组件
Widget _leftCateWidget(leftWidth) {
if (this._leftCateList.length > 0) {
return Container(
width: leftWidth,
height: double.infinity,
// color: Colors.red,
child: ListView.builder(
itemCount: this._leftCateList.length,
itemBuilder: (context, index) {
return Column(
children: <Widget>[
InkWell(
onTap: () {
setState(() {
// setState(() {
_selectIndex = index;
this._getRightCateData(this._leftCateList[index].sId);
});
},
child: Container(
width: double.infinity,
height: ScreenAdaper.height(56),
padding: EdgeInsets.only(top: ScreenAdaper.height(24)),
child: Text("${this._leftCateList[index].title}",
textAlign: TextAlign.center),
color: _selectIndex == index
? Color.fromRGBO(240, 246, 246, 0.9)
: Colors.white,
),
),
Divider(height: 1),
],
);
},
),
);
} else {
return Container(
width: leftWidth,
height: double.infinity,
);
}
} //右侧组件:
Widget _rightCateWidget(rightItemWidth, rightItemHeigth) {
if (this._rightCateList.length > 0) {
return Expanded(
flex: 1,
child: Container(
padding: EdgeInsets.all(10),
height: double.infinity,
color: Color.fromRGBO(240, 246, 246, 0.9),
// color: Colors.blue,
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: rightItemWidth / rightItemHeigth,
crossAxisSpacing: 10,
mainAxisSpacing: 10),
itemCount: this._rightCateList.length,
itemBuilder: (context, index) {
//处理图片:
String pic=this._rightCateList[index].pic;
pic=Config.domain+pic.replaceAll('\\','/');
return Container(
// padding: EdgeInsets.all(ScreenAdaper.width(20)),
child: Column(
children: <Widget>[
AspectRatio(
aspectRatio: 1 / 1,
child: Image.network(
"${pic}",
fit: BoxFit.cover),
),
Container(
height: ScreenAdaper.height(32),
child: Text("${this._rightCateList[index].title}"),
)
],
),
);
},
),
),
);
} else {
return Expanded(
flex: 1,
child: Container(
padding: EdgeInsets.all(10),
height: double.infinity,
color: Color.fromRGBO(240, 246, 246, 0.9),
child: Text('加载中...'),
));
}
} Widget build(BuildContext context) {
ScreenAdaper.init(context); //计算右侧GridView宽高比:
var leftWidth = ScreenAdaper.getScreenWidth() / 4;
//右侧宽高=总宽度-左侧宽度-Gridview外层元素左右的Padding值-GridView中间的间距
var rightItemWidth =
(ScreenAdaper.getScreenWidth() - leftWidth - 20 - 20) / 3;
rightItemWidth = ScreenAdaper.width(rightItemWidth);
var rightItemHeigth = rightItemWidth + ScreenAdaper.height(32); return Row(
children: <Widget>[
_leftCateWidget(leftWidth),
_rightCateWidget(rightItemWidth, rightItemHeigth)
],
);
}
}
09 Flutter底部Tab切换保持页面状态的几种方法的更多相关文章
- Android典型界面设计——FragmentTabHost+Fragment实现底部tab切换
一.问题描述 在上次博文中,我们使用RadioGroup+ViewPage+Fragmen实现了顶部滑动导航(查看文章:http://www.cnblogs.com/jerehedu/p/460759 ...
- 用 CSS 隐藏页面元素的 5 种方法
原文链接:用 CSS 隐藏页面元素的 5 种方法,转载请注明来源! 用 CSS 隐藏页面元素有许多种方法.你可以将 opacity 设为 0.将 visibility 设为 hidden.将 disp ...
- CSS 隐藏页面元素的 几 种方法总结
用 CSS 隐藏页面元素有许多种方法.你可以将 opacity 设为 0.将 visibility 设为 hidden.将 display 设为 none 或者将 position 设为 absolu ...
- YbSoftwareFactory 代码生成插件【二十五】:Razor视图中以全局方式调用后台方法输出页面代码的三种方法
上一篇介绍了 MVC中实现动态自定义路由 的实现,本篇将介绍Razor视图中以全局方式调用后台方法输出页面代码的三种方法. 框架最新的升级实现了一个页面部件功能,其实就是通过后台方法查询数据库内容,把 ...
- React Router v4 页面传值的三种方法
传值方法 1.props.params 使用React router定义路由时,我们可以给指定一个path,然后指定通配符可以携带参数到指定的path: <Route path='/user/: ...
- js刷新页面有哪几种方法
js刷新页面有哪几种方法 一.总结 一句话总结:location属性的reload方法即可:document.location.reload() 1.页面刷新有哪常见的8种方法? 1,history. ...
- AE控制图层中要素可见状态的几种方法
转自原文 AE控制图层中要素可见状态的几种方法 工作中常有这样的需求,一个作业图层由几个作业员来操作,我们要 控制每一个作业员只能看到他负责的区域.作业员的可见区域控制有时候是按空间区域划分,有时候是 ...
- 在React中跨组件分发状态的三种方法
在React中跨组件分发状态的三种方法 当我问自己第一百次时,我正在研究一个典型的CRUD屏幕:"我应该将状态保留在这个组件中还是将其移动到父组件?". 如果需要对子组件的状态进行 ...
- Python+Selenium自动化-定位页面元素的八种方法
Python+Selenium自动化-定位页面元素的八种方法 本篇文字主要学习selenium定位页面元素的集中方法,以百度首页为例子. 0.元素定位方法主要有: id定位:find_elemen ...
随机推荐
- Java基于Redis的分布式锁
分布式锁,其实最终还是要保证锁(数据)的一致性,说到数据一致性,基于ZK,ETCD数据一致性中间件做分数是锁,才是王道.但是Redis也能满足最基本的需求. 参考: https://www.cnblo ...
- 使用vs编写arduino项目
说实话,arduino官方自带的编辑器有时候用的真不爽.所以直接使用vs开发arduino项目,用起来真爽,一直使用一直爽. 不多废话,直接上图,三部曲结束,搞定,收工. 我用的是vs2015版本的. ...
- H5中的requestAnimationFrame
这两天做一个公告展示轮播的动画,刚开始是用setinterval写的,后来发现做出来的动画效果有抖动的现象,动画不流畅,遂决定试试requestAnimationFrame,之前也只是耳闻,没有用过, ...
- 浅谈sass与less区别优缺点
Sass是一种动态样式语言,Sass语法的缩排语法,比Css比多出很多功能,如变量,嵌套,运算,继承,颜色处理,函数等,易于阅读.Cass的安装需要安装Ruby环境,是服务器端处理的,Less是需要引 ...
- 队列(queue)和堆栈(stack)的学习
队列 1 . 先进先出 .队列尾进行插入,队列头进行删除,获取,修改. -----first come ,first served . --first in .first out ...
- net.exe和net1.exe的区别&联系.
system32文件夹下有一个net.exe和net1.exe,一般做渗透的时候,很多情况下管理员只知道删除net.exe而遗漏net1.exe,导致我们能继续do evil..... 一直没弄明白它 ...
- 0009SpringBoot静态资源访问路径
访问静态资源: 静态资源需要放在哪些路径下才能被访问呢: 通过WebMvcAutoConfiguration.java中 addResourceHandlers()方法查找绑定的路径,一个是通过web ...
- appium+python 【Mac】UI自动化测试封装框架介绍 <五>---脚本编写(多设备)
目的: 通过添加设备号,则自动给添加的设备分配端口,启动对应的appium服务.注意:为了方便,将共用一个配置文件. 1.公共的配置文件名称:desired_caps.yaml platformVer ...
- 机器学习mark一下
https://developers.google.cn/machine-learning/crash-course/ml-intro
- 一款超好用的第三方评论插件--Gittalk
使用GITALK的背景: 1. 最近在做一个基于Java的个人博客系统,已经基本完工了,突然发现怎么没有评论的操作,如果再从头开始从数据库开始写的话,花费的代价有点大,于是乎我就在网上寻找一款适合我的 ...