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,  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)),
      //  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),
                 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)),
       itemWidth,
      decoration:
      BoxDecoration(border: Border.all(color: Colors.black12,  1)),
      child: Column(
        children: <Widget>[
          Container(
             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(
         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(
                     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(
         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)
      ],
    );
  }
}

  

原文地址:https://www.cnblogs.com/yiweiyihang/p/11410269.html