You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter自定义Drawer点击已打开页面重复跳转问题求助

问题解决:Flutter Drawer菜单项重复跳转页面

问题描述

自定义Drawer与AppBar后,点击Drawer菜单项时预期效果为:

  • 若对应页面未打开:跳转至该页面并关闭Drawer
  • 若页面已打开:仅关闭Drawer,不重复跳转
    但当前点击已打开页面的Drawer项时,仍会重复打开该页面,自行添加的判断逻辑未生效。

错误原因

你当前的判断逻辑存在核心错误:

if (ModalRoute.of(context)?.settings.arguments is HomePage)

settings.arguments是传递给路由的参数,并非页面组件本身。你没有给HomePage路由传递任何参数,所以这个判断永远为false,导致每次都会执行跳转逻辑。

解决方案

方法一:通过路由名称判断(推荐)

利用你在HomePage中定义的静态路由名homerouter,直接判断当前路由的名称是否匹配:

步骤1:给SettingPage添加静态路由名

在SettingPage类中添加路由标识:

static const String settingRouter = '/settings';

步骤2:修改Drawer菜单项的判断逻辑

修改Home和Settings项的onTap方法:

Home项修改后代码
onTap: () {
  // 先关闭Drawer
  Navigator.pop(context);
  // 判断当前路由是否为HomePage的路由
  if (ModalRoute.of(context)?.settings.name != HomePage.homerouter) {
    // 非Home页面时才执行跳转
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => const HomePage(),
        // 显式设置路由名称,确保判断生效
        settings: const RouteSettings(name: HomePage.homerouter),
      ),
    );
  }
},
Settings项修改后代码
onTap: () {
  Navigator.pop(context);
  if (ModalRoute.of(context)?.settings.name != SettingPage.settingRouter) {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => const SettingPage(),
        settings: const RouteSettings(name: SettingPage.settingRouter),
      ),
    );
  }
},

方法二:通过页面类型判断

如果不使用路由名称,也可以直接判断当前页面的组件类型:

onTap: () {
  Navigator.pop(context);
  final currentRoute = ModalRoute.of(context);
  // 判断当前路由的页面是否为HomePage
  if (currentRoute is MaterialPageRoute && 
      currentRoute.builder(context) is! HomePage) {
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => const HomePage()),
    );
  }
},

修改后的完整Drawer代码

import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:lottie/lottie.dart';
import 'package:simplethread/src/auth/auth_service.dart';
import 'package:simplethread/src/screens/home.dart';
import 'package:simplethread/src/screens/setting_page.dart';

class MyDrawer extends StatelessWidget {
  const MyDrawer({super.key});
  final String _animation = 'assets/animation/login_message.json';

  void logout() {
    final _auth = AuthService();
    _auth.signOut();
  }

  @override
  Widget build(BuildContext context) {
    return Drawer(
      backgroundColor: Theme.of(context).colorScheme.background,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Column(
            children: [
              const SizedBox(height: 60),
              Lottie.asset(
                _animation,
                fit: BoxFit.fill,
                width: 100,
                height: 100,
              ),
              Text(
                'Simple Thread',
                style: GoogleFonts.playfairDisplay(
                  textStyle: const TextStyle(
                    letterSpacing: .5,
                    fontSize: 20,
                    fontWeight: FontWeight.bold,
                    color: Colors.black,
                  ),
                ),
              ),
              const SizedBox(height: 25),

              // Home Page Item
              Padding(
                padding: const EdgeInsets.only(left: 25.0),
                child: ListTile(
                  title: Text(
                    "H O M E",
                    style: GoogleFonts.playfairDisplay(color: Colors.black),
                  ),
                  leading: const Icon(Icons.home_rounded),
                  onTap: () {
                    Navigator.pop(context);
                    if (ModalRoute.of(context)?.settings.name != HomePage.homerouter) {
                      Navigator.push(
                        context,
                        MaterialPageRoute(
                          builder: (context) => const HomePage(),
                          settings: const RouteSettings(name: HomePage.homerouter),
                        ),
                      );
                    }
                  },
                ),
              ),

              // Setting Page Item
              Padding(
                padding: const EdgeInsets.only(left: 25.0),
                child: ListTile(
                  title: Text(
                    "S E T T I N G S",
                    style: GoogleFonts.playfairDisplay(color: Colors.black),
                  ),
                  leading: const Icon(Icons.settings_rounded),
                  onTap: () {
                    Navigator.pop(context);
                    if (ModalRoute.of(context)?.settings.name != SettingPage.settingRouter) {
                      Navigator.push(
                        context,
                        MaterialPageRoute(
                          builder: (context) => const SettingPage(),
                          settings: const RouteSettings(name: SettingPage.settingRouter),
                        ),
                      );
                    }
                  },
                ),
              ),
            ],
          ),
          Padding(
            padding: const EdgeInsets.only(left: 25.0, bottom: 25.0),
            child: ListTile(
              title: Text(
                "L O G O U T",
                style: GoogleFonts.playfairDisplay(color: Colors.black),
              ),
              leading: const Icon(Icons.logout_rounded),
              onTap: logout,
            ),
          ),
        ],
      ),
    );
  }
}

补充说明

  • 必须确保SettingPage类中添加了static const String settingRouter = '/settings';
  • 路由名称的方式更灵活,后续修改页面组件时,只要路由名称不变,判断逻辑无需改动
  • 先执行Navigator.pop(context)关闭Drawer,再判断是否跳转,交互体验更流畅

内容的提问来源于stack exchange,提问作者Future Insight

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 00:40:22