所以,我用flutter web建立了一个网站。当我使用flutter run命令运行时,一切都很好,当我在URL中键入不存在的内容时,onUnknownRoute会被触发。但是当我使用flutter build web命令构建项目时,onUnknownRoute永远不会被触发。我已经在github页面上传了我的项目,但UnknownRoute从未被触发。我甚至不明白错误可能是什么,所以,我不知道我应该在这里发布什么作为容易出错的代码。如果我能得到一些帮助,我会很高兴的。非常感谢。
主要.dart
import 'package:flutter/material.dart';
import 'package:app/constants.dart';
import 'package:app/provider/themeProvider.dart';
import 'package:app/provider/themeStyles.dart';
import 'package:app/sections/error404.dart';
import 'package:app/sections/getInTouch/getInTouch.dart';
import 'package:app/sections/mainSection.dart';
import 'package:app/sections/serviceDetails/serviceDetails.dart';
import 'package:app/utils/routeConfiguration.dart';
import 'package:provider/provider.dart';
import 'package:url_strategy/url_strategy.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
setPathUrlStrategy();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
ThemeProvider _themeProvider = ThemeProvider();
void getCurrentAppTheme() async {
_themeProvider.lightTheme = await _themeProvider.darkThemePref.getTheme();
}
@override
void initState() {
getCurrentAppTheme();
super.initState();
}
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => ThemeProvider()),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'App',
theme: ThemeStyles.themeData(_themeProvider.lightTheme, context),
onGenerateRoute: RouteConfiguration.onGenerateRoute,
initialRoute: MainPage.Route,
onUnknownRoute: (settings) {
return CustomPageRoute(
builder: (_) => ErrorPage(),
// ignore: prefer_const_constructors
settings: RouteSettings(name: ErrorPage.Route));
},
),
);
}
}
routeConfiguration.dart
// ignore_for_file: prefer_const_constructors
import 'package:flutter/material.dart';
import 'package:app/sections/error404.dart';
import 'package:app/sections/mainSection.dart';
import 'package:app/utils/Path.dart';
class RouteConfiguration {
/// List of [Path] to for route matching. When a named route is pushed with
/// [Navigator.pushNamed], the route name is matched with the [Path.pattern]
/// in the list below. As soon as there is a match, the associated builder
/// will be returned. This means that the paths higher up in the list will
/// take priority.
static List<Path> paths = [
Path(
r'^' + ErrorPage.Route + '$',
(context, match) => ErrorPage(),
),
Path(
r'^' + ErrorPage.Route + '/$',
(context, match) => ErrorPage(),
),
];
/// The route generator callback used when the app is navigated to a named
/// route. Set it on the [MaterialApp.onGenerateRoute] or
/// [WidgetsApp.onGenerateRoute] to make use of the [paths] for route
/// matching.
static Route<dynamic> onGenerateRoute(RouteSettings settings) {
if (settings.name == "/") {
return CustomPageRoute(
builder: (context) => MainPage(),
settings: settings,
);
}
for (Path path in paths) {
final regExpPattern = RegExp(path.pattern!);
if (regExpPattern.hasMatch(settings.name!)) {
final firstMatch = regExpPattern.firstMatch(settings.name!);
final match = (firstMatch!.groupCount == 1) ? firstMatch.group(1) : null;
return CustomPageRoute(
builder: (context) {
return path.builder(context, match);
},
settings: RouteSettings(name: ErrorPage.Route),
);
}
}
// If no match was found, we let [WidgetsApp.onUnknownRoute] handle it.
return CustomPageRoute(
builder: (_) => ErrorPage(),
settings: RouteSettings(name: ErrorPage.Route));
}
}
class CustomPageRoute extends PageRouteBuilder {
final Widget Function(dynamic)? builder;
final RouteSettings settings;
CustomPageRoute({this.builder, required this.settings})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) =>
builder!.call(context),
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) =>
FadeTransition(
opacity: animation,
child: ScaleTransition(
scale: Tween<double>(
begin: 0.5,
end: 1.0,
).animate(
CurvedAnimation(
parent: animation,
curve: Curves.fastOutSlowIn,
),
),
child: child,
),
),
settings: settings);
}
错误404.dart
// ignore_for_file: prefer_const_constructors
import 'dart:ui';
import 'package:flutter/rendering.dart';
import 'package:app/animations/glitchAnimation.dart';
import 'package:app/provider/themeProvider.dart';
import 'package:app/sections/mainSection.dart';
import 'package:app/utils/animatedUFO.dart';
import 'package:app/utils/star_field.dart';
import 'package:app/widget/adaptiveText.dart';
import 'package:mouse_parallax/mouse_parallax.dart';
import 'package:provider/provider.dart';
import 'package:seo_renderer/seo_renderer.dart';
import 'package:flutter/material.dart';
import 'package:app/animations/entranceFader.dart';
import 'package:app/sections/navBar/navBarLogo.dart';
class ErrorPage extends StatefulWidget {
static const String Route = "/404";
@override
_ErrorPageState createState() => _ErrorPageState();
}
class _ErrorPageState extends State<ErrorPage>
with SingleTickerProviderStateMixin {
final globalKey = GlobalKey<ScaffoldState>();
ThemeProvider _themeProviders = ThemeProvider();
bool isPressed = false;
bool _isScrollingDown = false;
ScrollController _scrollController = ScrollController();
static const double idleSpeed = .2;
static const int starAnimDurationIn = 4500;
ValueNotifier<double> _speedValue = ValueNotifier(idleSpeed);
late AnimationController _starAnimController;
late Animation<double> _starAnimSequence;
@override
void initState() {
_scrollController = _themeProviders.scroll;
_scrollController.addListener(() {
if (_scrollController.position.userScrollDirection ==
ScrollDirection.reverse) {
if (!_isScrollingDown) {
_isScrollingDown = true;
setState(() {});
}
}
if (_scrollController.position.userScrollDirection ==
ScrollDirection.forward) {
if (_isScrollingDown) {
_isScrollingDown = false;
setState(() {});
}
}
});
_starAnimController = AnimationController(
vsync: this,
duration: Duration(milliseconds: starAnimDurationIn),
reverseDuration: Duration(milliseconds: starAnimDurationIn ~/ 3),
);
_starAnimController.addListener(() {
_speedValue.value = _starAnimSequence.value;
});
//Create an animation sequence that moves our stars back, then forwards, then to rest at 0.
//This will be played each time we load a detail page, to create a flying through space transition effect
_starAnimSequence = TweenSequence([
TweenSequenceItem<double>(
tween: Tween<double>(begin: idleSpeed, end: -2)
.chain(CurveTween(curve: Curves.easeOut)),
weight: 20.0,
),
TweenSequenceItem<double>(
tween: Tween<double>(begin: -2, end: 20)
.chain(CurveTween(curve: Curves.easeOut)),
weight: 30.0,
),
TweenSequenceItem<double>(
tween: Tween<double>(begin: 20, end: 0)
.chain(CurveTween(curve: Curves.easeOut)),
weight: 50.0,
)
]).animate(_starAnimController);
super.initState();
// WidgetsBinding.instance?.addPostFrameCallback((_) {
// if (regExpBots.hasMatch(window.navigator.userAgent.toString()) && (globalKey.currentState != null)) {
// globalKey.currentState.openDrawer();
// }
// });
}
@override
void dispose() {
_scrollController.dispose();
_scrollController.removeListener(() {});
_starAnimController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final _themeProv = Provider.of<ThemeProvider>(context);
double _height = MediaQuery.of(context).size.height;
int starCount = 400;
return Container(
child: Stack(
children: [
Container(
width: double.maxFinite,
height: double.maxFinite,
child: ImageRenderer(
alt: 'Background Image For Decoration',
link: 'assets/logos/i8.jpg',
child: Image.asset(
'assets/logos/i8.jpg',
fit: BoxFit.cover,
),
),
),
BackdropFilter(
filter: ImageFilter.blur(
sigmaX: 30.0,
sigmaY: 30.0,
),
child: Scaffold(
key: globalKey,
extendBodyBehindAppBar: true,
backgroundColor: _themeProv.lightTheme
? Colors.white
: Colors.black.withOpacity(0.0),
appBar: (MediaQuery.of(context).size.width < 860)
? AppBar(
automaticallyImplyLeading: false,
iconTheme: IconThemeData(
color: _themeProv.lightTheme
? Color(0xff1C1C28)
: Colors.white),
elevation: 0,
backgroundColor: Colors.transparent,
actions: [
GestureDetector(
onTap: () {
Navigator.pushNamedAndRemoveUntil(
context, MainPage.Route, (c) {
return false;
});
},
child: NavBarLogo(),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.05,
)
],
)
: _appBarTabDesktop(_themeProv),
body: Stack(
children: [
ValueListenableBuilder<double>(
valueListenable: _speedValue,
builder: (context, value, child) {
//Scrolling star background
return StarField(starSpeed: value, starCount: starCount);
},
),
Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 27.0),
child: ParallaxStack(
resetOnExit: true,
useLocalPosition: true,
referencePosition: 0.6,
dragCurve: Curves.easeIn,
resetCurve: Curves.bounceOut,
layers: [
ParallaxLayer(
yRotation: 0.80,
xRotation: 0.80,
xOffset: 90,
yOffset: 80,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: TextRenderer(
text: GlithEffect(
child: AdaptiveText(
"404",
style: TextStyle(
fontSize: _height * 0.1,
fontFamily: 'Montserrat',
fontWeight: FontWeight.w900,
color: Colors.white,
),
),
),
),
),
SizedBox(
height: _height * 0.02,
),
TextRenderer(
text: AdaptiveText(
"We searched as far as we could, but were unable to find the page you were looking for.nSorry.",
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Ubuntu',
fontSize: _height * 0.02,
color: Colors.white,
height: 2.0,
),
),
),
],
),
),
],
),
),
),
],
),
),
),
],
),
);
}
AppBar _appBarTabDesktop(ThemeProvider _themeProv) {
return AppBar(
elevation: 0.0,
backgroundColor:
_themeProv.lightTheme ? Colors.white : Colors.transparent,
automaticallyImplyLeading: false,
centerTitle: false,
title: MediaQuery.of(context).size.width < 780
? EntranceFader(
duration: Duration(milliseconds: 250),
offset: Offset(0, -10),
delay: Duration(seconds: 3),
child: GestureDetector(
onTap: () {
Navigator.pushNamedAndRemoveUntil(context, MainPage.Route,
(c) {
return false;
});
},
child: NavBarLogo(
height: 37.0,
),
))
: EntranceFader(
offset: Offset(0, -10),
duration: Duration(milliseconds: 250),
delay: Duration(milliseconds: 100),
child: GestureDetector(
onTap: () {
Navigator.pushNamedAndRemoveUntil(context, MainPage.Route,
(c) {
return false;
});
},
child: NavBarLogo(
height: MediaQuery.of(context).size.height * 0.065,
),
),
),
);
}
}
此外,我在github页面的自定义404页面的其他解决方案中读到,我需要一个自定义域才能工作。所以,这就是造成我问题的原因。
您应该使用Navigator v2 for web。它有更多的功能,使使用web路由变得非常容易。