addLocalHistoryEntry method
- LocalHistoryEntry entry
Adds a local history entry to this route.
When asked to pop, if this route has any local history entries, this route will handle the pop internally by removing the most recently added local history entry.
The given local history entry must not already be part of another local history route.
HomePage
and SecondPage
.
The HomePage
can navigate to the SecondPage
.
The SecondPage
uses a LocalHistoryEntry to implement local navigation
within that page. Pressing 'show rectangle' displays a red rectangle and
adds a local history entry. At that point, pressing the '< back' button
pops the latest route, which is the local history entry, and the red
rectangle disappears. Pressing the '< back' button a second time
once again pops the latest route, which is the SecondPage
, itself.
Therefore, the second press navigates back to the HomePage
.
class App extends StatelessWidget {
const App({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/',
routes: <String, WidgetBuilder>{
'/': (BuildContext context) => const HomePage(),
'/second_page': (BuildContext context) => const SecondPage(),
},
);
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text('HomePage'),
// Press this button to open the SecondPage.
ElevatedButton(
child: const Text('Second Page >'),
onPressed: () {
Navigator.pushNamed(context, '/second_page');
},
),
],
),
),
);
}
}
class SecondPage extends StatefulWidget {
const SecondPage({super.key});
@override
State<SecondPage> createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
bool _showRectangle = false;
Future<void> _navigateLocallyToShowRectangle() async {
// This local history entry essentially represents the display of the red
// rectangle. When this local history entry is removed, we hide the red
// rectangle.
setState(() => _showRectangle = true);
ModalRoute.of(context)?.addLocalHistoryEntry(
LocalHistoryEntry(
onRemove: () {
// Hide the red rectangle.
setState(() => _showRectangle = false);
}
)
);
}
@override
Widget build(BuildContext context) {
final Widget localNavContent = _showRectangle
? Container(
width: 100.0,
height: 100.0,
color: Colors.red,
)
: ElevatedButton(
onPressed: _navigateLocallyToShowRectangle,
child: const Text('Show Rectangle'),
);
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
localNavContent,
ElevatedButton(
child: const Text('< Back'),
onPressed: () {
// Pop a route. If this is pressed while the red rectangle is
// visible then it will pop our local history entry, which
// will hide the red rectangle. Otherwise, the SecondPage will
// navigate back to the HomePage.
Navigator.of(context).pop();
},
),
],
),
),
);
}
}
Implementation
void addLocalHistoryEntry(LocalHistoryEntry entry) {
assert(entry._owner == null);
entry._owner = this;
_localHistory ??= <LocalHistoryEntry>[];
final bool wasEmpty = _localHistory!.isEmpty;
_localHistory!.add(entry);
bool internalStateChanged = false;
if (entry.impliesAppBarDismissal) {
internalStateChanged = _entriesImpliesAppBarDismissal == 0;
_entriesImpliesAppBarDismissal += 1;
}
if (wasEmpty || internalStateChanged) {
changedInternalState();
}
}