09 Flutter底部Tab切换保持页面状态的几种方法
IndexedStack:保此所有页面的状态:
AutomaticKeepAliveClientMixin:保此部分页面的状态:
修改的页面代码:
页面效果:
Tabs.dart
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) ], ); } }