如何在页面视图之间导航时保留底部导航



我有4个页面视图,每个页面都有各自的底部导航器。在第一个索引处,我正在执行一个导航到第4页的函数。然而,导航后,底部导航消失,这是不一致的。我如何使它保持一致。。,

class HomePage extends StatefulWidget {
HomePage({
Key key,
this.category,
this.shopname,
}) : super(key: key); //update this to   include the uid in the constructor
final String shopname;
final DocumentSnapshot category;
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {

页面控制器,

PageController _tabsPageController;
int _selectedTab = 0;
@override
void initState() {
_tabsPageController = PageController();
super.initState();
}
@override
void dispose() {
_tabsPageController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: PageView(
controller: _tabsPageController,
onPageChanged: (num) {
setState(() {
_selectedTab = num;
});
},
children: [

导航器在着陆页

LandingPage(), //<<================
SavedTab(
shopname: widget.shopname,
),
MyDrawer(),

导航到主页((

HomeTab()      //<<================
],
),
),
BottomTabs(
selectedTab: _selectedTab,
tabPressed: (num) {
_tabsPageController.animateToPage(num,
duration: Duration(milliseconds: 300),
curve: Curves.easeOutCubic);
},
),
],
),
);
}
}

您实际上只需要底部导航栏就可以路由到所需的页面。它基本上渲染BottomNavBar小部件内的所有屏幕,因此底部导航栏始终显示。这里有一个例子:

class BottomNavBar extends StatefulWidget {
@override
_BottomNavBarState createState() => _BottomNavBarState();
}
class _BottomNavBarState extends State<BottomNavBar> {
int _selectedIndex = 0;
static List<Widget> _widgetOptions = <Widget>[
Screen1(),
Screen2(),
Screen3(),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
bottomNavigationBar: BottomNavigationBar(
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.dashboard),
label: 'Screen 1',
),
BottomNavigationBarItem(
icon: Icon(Icons.work),
label: 'Screen 2',
),
BottomNavigationBarItem(
icon: Icon(Icons.directions_car),
label: 'Screen 3',
),
],
currentIndex: _selectedIndex,
onTap: _onItemTapped,
),
);
}
}

如果它对你有用,请在评论中告诉我。

检查我的代码

  • https://github.com/hoc081098/Movie-Ticket-Booking/blob/master/MobileApp/datn/lib/ui/app_scaffold.dart或
  • https://github.com/hoc081098/nested_navigation

自定义脚手架

class AppScaffold extends StatefulWidget {
final List<BottomNavigationBarItem> items;
final List<AppScaffoldWidgetBuilder> builders;
const AppScaffold({
Key? key,
required this.items,
required this.builders,
}) : super(key: key);
@override
_AppScaffoldState createState() => _AppScaffoldState();
static NavigatorState navigatorOfCurrentIndex(
BuildContext context, {
AppScaffoldIndex? switchToNewIndex,
}) {
final appScaffoldState =
context is StatefulElement && context.state is _AppScaffoldState
? context.state as _AppScaffoldState
: context.findAncestorStateOfType<_AppScaffoldState>()!;
final currentIndex = appScaffoldState.currentIndex;
final navigatorKeys = appScaffoldState.navigatorKeys;
final newIndex = switchToNewIndex?.rawValue;
if (newIndex != null &&
newIndex != currentIndex &&
appScaffoldState.mounted) {
appScaffoldState.onTap(newIndex);
return navigatorKeys[newIndex].currentState!;
}
return navigatorKeys[currentIndex].currentState!;
}
static NotReplayValueStream<AppScaffoldIndex> currentIndexStream(
BuildContext context) =>
context.findAncestorStateOfType<_AppScaffoldState>()!.indexS;
static NavigatorState navigatorByIndex(
BuildContext context,
AppScaffoldIndex index,
) {
final appScaffoldState =
context.findAncestorStateOfType<_AppScaffoldState>()!;
return appScaffoldState.navigatorKeys[index.rawValue].currentState!;
}
}
class _AppScaffoldState extends State<AppScaffold> with DisposeBagMixin {
var navigatorKeys = <GlobalKey<NavigatorState>>[];
final indexS = ValueSubject(AppScaffoldIndex.home, sync: true);
@pragma('vm:prefer-inline')
@pragma('dart2js:tryInline')
int get currentIndex => indexS.requireValue.rawValue;
@override
void initState() {
super.initState();
navigatorKeys = List.generate(
widget.builders.length,
(_) => GlobalKey<NavigatorState>(),
);
indexS.disposedBy(bag);
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
final navigatorState = navigatorKeys[currentIndex].currentState!;
final canPop = navigatorState.canPop();
if (canPop) {
navigatorState.maybePop();
}
if (!canPop && currentIndex > 0) {
onTap(0);
return Future.value(false);
}
return Future.value(!canPop);
},
child: RxStreamBuilder<AppScaffoldIndex>(
stream: indexS,
builder: (context, snapshot) {
final index = snapshot!.rawValue;
return Scaffold(
body: buildBody(index),
bottomNavigationBar: BottomNavigationBar(
items: widget.items,
type: BottomNavigationBarType.fixed,
currentIndex: index,
onTap: onTap,
),
);
},
),
);
}
void onTap(final int newIndex) {
if (currentIndex == newIndex) {
navigatorKeys[currentIndex]
.currentState
?.popUntil((route) => route.isFirst);
} else {
indexS.add(_fromRawValue(newIndex));
}
}
Widget buildBody(int index) {
return IndexedStack(
index: index,
children: [
for (int i = 0; i < widget.builders.length; i++)
Navigator(
key: navigatorKeys[i],
onGenerateRoute: (settings) => MaterialPageRoute(
settings: settings,
builder: (context) => widget.builders[i](context, settings),
),
observers: [
HeroController(),
],
)
],
);
}
}

主页

return AppScaffold(
key: appScaffoldKey,
builders: [
(context, settings) => homeRoutes[settings.name]!(context, settings),
(context, settings) =>
favoritesRoutes[settings.name]!(context, settings),
(context, settings) =>
notificationsRoutes[settings.name]!(context, settings),
(context, settings) => profileRoutes[settings.name]!(context, settings),
],
items: [
BottomNavigationBarItem(
icon: const Icon(Icons.home_rounded),
label: S.of(context).home,
),
BottomNavigationBarItem(
icon: const Icon(Icons.favorite_rounded),
label: S.of(context).favorites,
),
BottomNavigationBarItem(
icon: const Icon(Icons.notifications),
label: S.of(context).notifications,
),
BottomNavigationBarItem(
icon: const Icon(Icons.person_rounded),
label: S.of(context).profile,
),
],
);

最新更新