go-router结合flutter实现一个浏览器
使用 Flutter 和 GoRouter 实现浏览器式导航
是的,你可以使用 Flutter 和 GoRouter 来实现一个类似浏览器的导航体验,包括前进、后退、跳转到特定历史记录等功能。下面是一个完整的实现方案:
1. 基本架构设计
我们需要实现以下功能:
- 维护完整的导航历史记录
- 支持前进/后退操作
- 显示当前 URL
- 支持直接跳转到历史记录中的特定位置
2. 完整实现代码
2.1 主入口和路由配置
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
void main() {
runApp(const BrowserApp());
}
class BrowserApp extends StatefulWidget {
const BrowserApp({super.key});
@override
State<BrowserApp> createState() => _BrowserAppState();
}
class _BrowserAppState extends State<BrowserApp> {
late final GoRouter _router;
final _historyManager = NavigationHistoryManager();
@override
void initState() {
super.initState();
_router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => const HomePage(title: 'Home'),
),
GoRoute(
path: '/page1',
builder: (context, state) => const ContentPage(title: 'Page 1', color: Colors.blue),
),
GoRoute(
path: '/page2',
builder: (context, state) => const ContentPage(title: 'Page 2', color: Colors.green),
),
GoRoute(
path: '/page3',
builder: (context, state) => const ContentPage(title: 'Page 3', color: Colors.orange),
),
],
observers: [_historyManager], // 添加历史记录观察者
);
}
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerConfig: _router,
title: 'Flutter Browser',
debugShowCheckedModeBanner: false,
);
}
}
2.2 导航历史管理器
class NavigationHistoryManager extends NavigatorObserver {
final List<String> _history = [];
int _currentIndex = -1;
List<String> get history => _history;
int get currentIndex => _currentIndex;
String get currentRoute => _history.isNotEmpty ? _history[_currentIndex] : '';
bool get canGoBack => _currentIndex > 0;
bool get canGoForward => _currentIndex < _history.length - 1;
@override
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
if (route.settings.name != null) {
// 如果是前进操作,清除后面的历史
if (_currentIndex < _history.length - 1) {
_history.removeRange(_currentIndex + 1, _history.length);
}
_history.add(route.settings.name!);
_currentIndex = _history.length - 1;
}
}
@override
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
if (_currentIndex > 0) {
_currentIndex--;
}
}
void goToIndex(BuildContext context, int index) {
if (index >= 0 && index < _history.length) {
_currentIndex = index;
context.go(_history[index]);
}
}
void goBack(BuildContext context) {
if (canGoBack) {
_currentIndex--;
context.go(_history[_currentIndex]);
}
}
void goForward(BuildContext context) {
if (canGoForward) {
_currentIndex++;
context.go(_history[_currentIndex]);
}
}
}
2.3 页面组件实现
class HomePage extends StatelessWidget {
final String title;
const HomePage({super.key, required this.title});
@override
Widget build(BuildContext context) {
final historyManager = Navigator.of(context)
.widget
.observers
.whereType<NavigationHistoryManager>()
.first;
return Scaffold(
appBar: BrowserAppBar(historyManager: historyManager),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Welcome to Flutter Browser'),
const SizedBox(height: 20),
Wrap(
spacing: 10,
children: [
ElevatedButton(
onPressed: () => context.go('/page1'),
child: const Text('Go to Page 1'),
),
ElevatedButton(
onPressed: () => context.go('/page2'),
child: const Text('Go to Page 2'),
),
ElevatedButton(
onPressed: () => context.go('/page3'),
child: const Text('Go to Page 3'),
),
],
),
],
),
),
);
}
}
class ContentPage extends StatelessWidget {
final String title;
final Color color;
const ContentPage({super.key, required this.title, required this.color});
@override
Widget build(BuildContext context) {
final historyManager = Navigator.of(context)
.widget
.observers
.whereType<NavigationHistoryManager>()
.first;
return Scaffold(
appBar: BrowserAppBar(historyManager: historyManager),
backgroundColor: color.withOpacity(0.2),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(title, style: TextStyle(fontSize: 24, color: color)),
const SizedBox(height: 20),
Wrap(
spacing: 10,
children: [
ElevatedButton(
onPressed: () => context.go('/'),
child: const Text('Go Home'),
),
ElevatedButton(
onPressed: () => context.go('/page1'),
child: const Text('Go to Page 1'),
),
ElevatedButton(
onPressed: () => context.go('/page2'),
child: const Text('Go to Page 2'),
),
ElevatedButton(
onPressed: () => context.go('/page3'),
child: const Text('Go to Page 3'),
),
],
),
],
),
),
);
}
}
2.4 浏览器工具栏组件
class BrowserAppBar extends StatelessWidget implements PreferredSizeWidget {
final NavigationHistoryManager historyManager;
const BrowserAppBar({super.key, required this.historyManager});
@override
Widget build(BuildContext context) {
return AppBar(
title: Text(historyManager.currentRoute),
actions: [
IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: historyManager.canGoBack
? () => historyManager.goBack(context)
: null,
),
IconButton(
icon: const Icon(Icons.arrow_forward),
onPressed: historyManager.canGoForward
? () => historyManager.goForward(context)
: null,
),
PopupMenuButton<int>(
itemBuilder: (context) => historyManager.history
.asMap()
.entries
.map((entry) => PopupMenuItem(
value: entry.key,
child: Text(
entry.value,
style: TextStyle(
fontWeight: entry.key == historyManager.currentIndex
? FontWeight.bold
: FontWeight.normal,
),
),
))
.toList(),
onSelected: (index) => historyManager.goToIndex(context, index),
),
],
);
}
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}
更多关于go-router结合flutter实现一个浏览器的实战教程也可以访问 https://www.itying.com/category-92-b0.html