Flutter切换tab后保留tab状态

Flutter切换tab后保留tab状态

概述

Flutter中为了节约内存不会保存widget的状态,widget都是临时变量。当咱们使用TabBar,TabBarView是咱们就会发现,切换tab后再从新切换回上一页面,这时候tab会从新加载从新建立,体验很不友好。Flutter出于本身的设计考虑并无延续android的ViewPager这样的缓存页面设计,毕竟控件两端都要开发,目前还在beta版本有不少设计还不够完善,可是设计的拓展性没得说,flutter仍是为咱们提供了解决办法。咱们能够强制widget不显示状况下保留状态,下回再加载时就不用从新建立了。android

AutomaticKeepAliveClientMixin AutomaticKeepAliveClientMixin 是一个抽象状态,使用也很简单,咱们只须要用咱们本身的状态继承这个抽象状态,并实现 wantKeepAlive 方法便可。缓存

DefaultTabController 使用 AutomaticKeepAliveClientMixin 保持状态

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: TabBarDemo(),
    );
  }
}

class TabBarDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 3,
        child: Scaffold(
          appBar: AppBar(
            bottom: TabBar(
              tabs: [
                Tab(icon: Icon(Icons.directions_car)),
                Tab(icon: Icon(Icons.directions_transit)),
                Tab(icon: Icon(Icons.directions_bike)),
              ],
            ),
            title: Text('Tabs Demo'),
          ),
          body: TabBarView(
            children: [
              Page1(),
              Page2(),
              Page3(),
            ],
          ),
        ),
      ),
    );
  }
}

class Page1 extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _Page1State();
  }
}

class _Page1State extends State<Page1> with AutomaticKeepAliveClientMixin {
  @override
  void initState() {
    super.initState();
    print("Page 1 init");
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Text("Page 1");
  }

  @override
  bool get wantKeepAlive => true;
}

class Page2 extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _Page2State();
  }
}

class _Page2State extends State<Page2> with AutomaticKeepAliveClientMixin {
  @override
  void initState() {
    super.initState();
    print("Page 2 init");
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Text("Page 2");
  }

  @override
  bool get wantKeepAlive => true;
}

class Page3 extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _Page3State();
  }
}

class _Page3State extends State<Page3> with AutomaticKeepAliveClientMixin {
  @override
  void initState() {
    super.initState();
    print("Page 3 init");
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Text("Page 3");
  }

  @override
  bool get wantKeepAlive => true;
}
复制代码

BottomNavigationBar

方法一:使用 PageView 中保持状态
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

/// This Widget is the main application widget.
class MyApp extends StatelessWidget {
  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: MyStatefulWidget(),
    );
  }
}

class MyStatefulWidget extends StatefulWidget {
  MyStatefulWidget({Key key}) : super(key: key);

  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  int _selectedIndex = 0;
  static const TextStyle optionStyle =
      TextStyle(fontSize: 30, fontWeight: FontWeight.bold);

  static List<Widget> _widgetOptions = <Widget>[
    Page1(),
    Page2(),
    Page3(),
  ];

  // 增长 PageController
  final pageController = PageController();
  void onPageChanged(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  void _onItemTapped(int index) {
    // setState(() {
    //   _selectedIndex = index;
    // });
    // 使用 pageController jumpToPage 
    pageController.jumpToPage(index);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('BottomNavigationBar Sample'),
      ),
     body: PageView(
        children: _widgetOptions,
        controller: pageController,
        onPageChanged: onPageChanged,
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            title: Text('Home'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.business),
            title: Text('Business'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.school),
            title: Text('School'),
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.amber[800],
        onTap: _onItemTapped,
      ),
    );
  }
}

class Page1 extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _Page1State();
  }
}

class _Page1State extends State<Page1> with AutomaticKeepAliveClientMixin {
  @override
  void initState() {
    super.initState();
    print("Page 1 init");
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Text("Page 1");
  }

  @override
  bool get wantKeepAlive => true;
}

class Page2 extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _Page2State();
  }
}

class _Page2State extends State<Page2> with AutomaticKeepAliveClientMixin {
  @override
  void initState() {
    super.initState();
    print("Page 2 init");
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Text("Page 2");
  }

  @override
  bool get wantKeepAlive => true;
}

class Page3 extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _Page3State();
  }
}

class _Page3State extends State<Page3> with AutomaticKeepAliveClientMixin {
  @override
  void initState() {
    super.initState();
    print("Page 3 init");
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Text("Page 3");
  }

  @override
  bool get wantKeepAlive => true;
}

复制代码
方法二: 使用IndexedStack存储页面
_body = IndexedStack(
  children: <Widget>[
    Page1(),
    Page2(),
    Page3(),
  ],
  index: _selectedIndex,
);

复制代码
相关文章
相关标签/搜索