如何在flutter中正确地实现一条主路径和其他子路径的流畅页面导航?

col17t5w  于 2023-03-13  发布在  Flutter
关注(0)|答案(1)|浏览(118)

我是flutter的新手,我正在尝试构建一个trip advisor应用程序来扩展我的技能。我遇到的问题是,我不知道如何在一个复杂的应用程序中正确地实现flutter中的路线导航。我目前正在构建用户可以选择位置的主页(一个国家)。点击位置控件后,指向该位置的城市页面将被推到屏幕上。为了更好地理解,我附上了一张页面外观的图片:Locations + SubLocation Pages .
我不知道最合乎逻辑的方法是让应用栏根据页面上下文动态变化,同时添加一个“后退”按钮,弹出堆栈中的当前屏幕,以及如何保持相同的底部导航栏,而不必重建它。
这是我的主.dart文件

void main() async {
  runApp(const MainApp());
}

class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: MainTheme,
      initialRoute: '/mainpage',
      routes: {
        '/onboard': (context) => const OnboardingPage(),
        '/signup': (context) => const AuthPage(),
        '/mainpage': (context) => const MainPage(),
        '/locations': (context) => const LocationsPage(),
        '/state-screen': (context) => StateScreen(),
      },
    );
  }
}

我的主页

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  List pages = [const HomePage(), const FavoritesPage(), const LocationsPage()];

  int currentIndex = 2;

  void onTap(int index) {
    setState(
      () {
        currentIndex = index;
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        leading: Builder(
          builder: (BuildContext context) {
            return IconButton(
              icon: Image.asset(
                'assets/icons/sideMenuArrow@2x.png',
                width: 25,
                height: 14,
                // note: fix focus radius, probably image scale
              ),
              onPressed: () {
                Scaffold.of(context).openDrawer();
              },
            );
          },
        ),
        bottomOpacity: 0.0,
        elevation: 0.0,
        title: const Text(
          'LOCATION',
          style: TextStyle(color: Colors.black),
        ),
      ),
      body: pages[currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        type: BottomNavigationBarType.fixed,
        selectedItemColor: kSecondaryColor,
        backgroundColor: Colors.white,
        unselectedItemColor: Colors.grey.withOpacity(0.5),
        unselectedFontSize: 0,
        showUnselectedLabels: false,
        showSelectedLabels: false,
        onTap: onTap,
        currentIndex: currentIndex,
        items: const [
          BottomNavigationBarItem(
            label: 'Home',
            icon: Icon(Icons.home),
          ),
          BottomNavigationBarItem(
            label: 'Favorites',
            icon: Icon(Icons.favorite),
          ),
          BottomNavigationBarItem(
            label: 'Locations',
            icon: Icon(Icons.business_center),
          ),
          BottomNavigationBarItem(
            label: 'Calendar',
            icon: Icon(Icons.calendar_month),
          ),
          BottomNavigationBarItem(
            label: 'Account',
            icon: Icon(Icons.person),
          ),
        ],
      ),
    );
  }
}

和我的位置页面:

class LocationsPage extends StatefulWidget {
  const LocationsPage({super.key});

  @override
  State<LocationsPage> createState() => _LocationsPageState();
}

class _LocationsPageState extends State<LocationsPage> {
  List<LocationsDemo> locationsDemo = LocationsDemo.locationList;
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Column(
        children: [
          Expanded(
            child: ListView.builder(
              primary: true,
              scrollDirection: Axis.vertical,
              itemCount: locationsDemo.length,
              itemBuilder: (BuildContext context, int index) {
                return LocationsDemoList(
                  locationsDemo: locationsDemo[index],
                  callback: () => Navigator.pushNamed(context, '/state-screen'),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

我认为我的配置不干净,但我不知道如何改进它。按照我的逻辑,我应该有一个主页面,并带有一个支架、一个AppBar、内容和底部导航栏,就像我编写的代码一样。问题是,在Location Page小部件中,我推送了State Page,它没有支架小部件。而且它的代码和位置页面是一样的。所以我不得不重用主页面的AppBar和底部导航条代码,这对我来说对这种类型的导航没有意义。
在整个屏幕上推送状态页不是我想要的结果,因为我认为不应该在用户每次导航到子路径时重建Appbar、scaffold和底部导航栏。只有一些Appbar内容应该动态更改。
由于我的配置是错误的,我认为我应该做的是完全去掉Main Page小部件,并且由于Location Page应该是用户登录应用程序时显示的第一个页面,因此构建Scaffold,其中包含应用程序栏和底部导航栏。
编辑:我发现了一个类似的问题:
Bottom navigation Bar with sub navigators for each tab
如果我找到了解决方案,我会尝试实现它并编辑帖子,但基本上这是我试图达到的效果,一个类似于instagram和twitter应用程序的导航。

fnvucqvd

fnvucqvd1#

return Scaffold(
 appbar: AppBar(),
body: SafeArea(
  child: Column(
    children: [
      Expanded(
        child: ListView.builder(
          primary: true,
          scrollDirection: Axis.vertical,
          itemCount: locationsDemo.length,
          itemBuilder: (BuildContext context, int index) {
            return LocationsDemoList(
              locationsDemo: locationsDemo[index],
              callback: () => Navigator.pushAndRemoveUntil(context, '/state- 
         screen'),
            );
          },
        ),
      ),
    ],
  ),
);

使用Scaffold Package safeArea以获取AppBar,并使用Navigator.pushAndRemoveUntil导航页面,但不返回。

相关问题