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,
);

複製代碼
相關文章
相關標籤/搜索