Flutter:在页面之间导航时,持久底部导航栏会重建所有页面

问题描述 投票:0回答:2

我正在使用 persistent_bottom_nav_bar 包并实现了它的自定义导航栏(基本上只是根据其自述文件页面中的示例进行自定义)。下面是可重现的代码。

问题:当您使用底部导航进行导航时,每次点击都会重建所有页面。非常消耗应用程序的性能!一般来说,这似乎是一个 Flutter 问题,解决方案是通过使用例如一个 IndexedStack 当完整代码是自己编写而不是使用包时,我已经这样做了。

使用 persist_bottom_nav_bar 包时,特别是使用我使用的自定义代码时,有什么方法可以解决此问题吗?

我的代码(经过简化,以便任何人都可以复制并运行它):

main.dart

import 'package:flutter/material.dart';
import 'package:persistent_bottom_nav_bar/persistent-tab-view.dart';

import 'page1.dart';
import 'page2.dart';
import 'page3.dart';
import 'page4.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Demo',
      home: HomeScaffold(),
    );
  }
  }

class HomeScaffold extends StatefulWidget {

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

class _HomeScaffoldState extends State<HomeScaffold> {
  PersistentTabController _controller;

  @override
  void initState() {
    super.initState();
    _controller = PersistentTabController(initialIndex: 0);
  }

  List<Widget> _buildScreens() {
    return [
      Page1(),
      Page2(),
      Page3(),
      Page4(),
    ];
  }

  List<PersistentBottomNavBarItem> _navBarsItems() {
    return [
      _buildBottomNavBarItem('Page 1', Icons.home),
      _buildBottomNavBarItem('Page 2', Icons.search),
      _buildBottomNavBarItem('Page 3', Icons.message),
      _buildBottomNavBarItem('Page 4', Icons.settings),
    ];
  }

  @override
  Widget build(BuildContext context) {
    return PersistentTabView.custom(
      context,
      controller: _controller,
      screens: _buildScreens(),
      confineInSafeArea: true,
      itemCount: 4,
      handleAndroidBackButtonPress: true,
      stateManagement: true,
      screenTransitionAnimation: ScreenTransitionAnimation(
        animateTabTransition: true,
        curve: Curves.ease,
        duration: Duration(milliseconds: 200),
      ),
      customWidget: CustomNavBarWidget(
        items: _navBarsItems(),
        onItemSelected: (index) {
          setState(() {
            _controller.index = index;
          });
        },
        selectedIndex: _controller.index,
      ),
      // ),
    );
  }
}

class CustomNavBarWidget extends StatelessWidget {
  final int selectedIndex;
  final List<PersistentBottomNavBarItem> items;
  final ValueChanged<int> onItemSelected;

  CustomNavBarWidget({
    Key key,
    this.selectedIndex,
    @required this.items,
    this.onItemSelected,
  });

  Widget _buildItem(PersistentBottomNavBarItem item, bool isSelected) {
    return Container(
      alignment: Alignment.center,
      height: kBottomNavigationBarHeight,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Flexible(
            child: IconTheme(
              data: IconThemeData(
                  size: 26.0,
                  color: isSelected
                      ? (item.activeColorSecondary == null
                      ? item.activeColorPrimary
                      : item.activeColorSecondary)
                      : item.inactiveColorPrimary == null
                      ? item.activeColorPrimary
                      : item.inactiveColorPrimary),
              child: isSelected ? item.icon : item.inactiveIcon ?? item.icon,
            ),
          ),
          Padding(
            padding: const EdgeInsets.only(top: 5.0),
            child: Material(
              type: MaterialType.transparency,
              child: FittedBox(
                  child: Text(
                    item.title,
                    style: TextStyle(
                        color: isSelected
                            ? (item.activeColorSecondary == null
                            ? item.activeColorPrimary
                            : item.activeColorSecondary)
                            : item.inactiveColorPrimary,
                        fontWeight: FontWeight.w400,
                        fontSize: 12.0),
                  )),
            ),
          )
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child: Container(
        width: double.infinity,
        height: kBottomNavigationBarHeight,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: items.map((item) {
            int index = items.indexOf(item);
            return Flexible(
              child: GestureDetector(
                onTap: () {
                  this.onItemSelected(index);
                },
                child: _buildItem(item, selectedIndex == index),
              ),
            );
          }).toList(),
        ),
      ),
    );
  }
}

PersistentBottomNavBarItem _buildBottomNavBarItem(String title, IconData icon) {
  return PersistentBottomNavBarItem(
    icon: Icon(icon),
    title: title,
    activeColorPrimary: Colors.indigo,
    inactiveColorPrimary: Colors.grey,
  );
}
flutter flutter-dependencies
2个回答
0
投票

尝试使用AutomaticKeepAliveClientMixin,这在更改选项卡时不会刷新页面:

1.

  class PageState extends State<Page> with AutomaticKeepAliveClientMixin {
  1. @override
    bool get wantKeepAlive => true;
    
  2. @override
    Widget build(BuildContext context) {
      super.build(context);
    

0
投票

我遇到了同样的问题,我通过将indexedStack添加到底部导航小部件的主体来解决

 @override
  Widget build(BuildContext context) {
    return Scaffold(
        **//Starts here**
        body: IndexedStack(
        index: _selectedIndex,
        children: <Widget>[
          const LoginPage(),
          const ForYou(),
          const UserProfilePage(),
        ],
      ),
      **//Ends here**

      bottomNavigationBar: Container(
        decoration: BoxDecoration(
          borderRadius: const BorderRadius.vertical(top: Radius.circular(0)),
          border: Border.all(
            color: const Color.fromARGB(255, 209, 203, 203),
            width: 2,
          ),
        ),
        child: BottomNavigationBar(
          items: const <BottomNavigationBarItem>[
            BottomNavigationBarItem(
              icon: Icon(Icons.login),
              label: 'Login',
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.home),
              label: 'For You',
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.account_circle),
              label: 'My Profile',
            ),
          ],
          currentIndex: _selectedIndex,
          onTap: _onItemTapped,
          selectedLabelStyle: const TextStyle(
            color: Colors.black,
            fontFamily: 'Poppins',
          ),
          unselectedLabelStyle: const TextStyle(
            color: Colors.black,
            fontFamily: 'Poppins',
          ),
          type: BottomNavigationBarType.fixed,
          selectedItemColor: const Color.fromARGB(
              255, 11, 55, 150), 
          unselectedItemColor: Colors.black,
          backgroundColor: Colors.white,
          elevation: 7,
        ),
      ),
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.