我想让外部页面上的底部导航菜单保持颤动
I want to keep the bottom navigation menu on external page in flutter
我实现了不同类型的菜单(底部导航栏、cupertino 和自定义导航栏),但没有解决问题。
我不想使用应用栏返回,只能使用菜单。
所以工作流程将是这样的:3 个按钮 - 提要、主页和个人资料。
在菜单的主页上,我将有一个按钮。当我按下那个按钮时,我想显示菜单,即使那一刻没有按钮处于活动状态。
cupertino 解决方案对我有用,但我遇到了问题。主页按钮处于活动状态,我无法返回主屏幕。
class Menu extends StatefulWidget {
const Menu({Key? key}) : super(key: key);
@override
_MenuState createState() => _MenuState();
}
class _MenuState extends State<Menu> {
int _currentIndex = 1;
final List _children = [
Feed(),
Home(),
Profile(),
];
@override
Widget build(BuildContext context) {
return CupertinoTabScaffold(
backgroundColor: Colors.transparent,
tabBar: CupertinoTabBar(
onTap: onTabTapped, // new
currentIndex: _currentIndex,
//type: BottomNavigationBarType.fixed, // Fixed
backgroundColor: Colors.white, // <-- This works for fixed
//unselectedItemColor: Color(0xff221F1E),
//selectedItemColor: Color(0xffE4BDB6),
//showSelectedLabels: false,
//showUnselectedLabels: false,
items: [
BottomNavigationBarItem(
icon: new Icon(Icons.chat_rounded, size: 28),
label: 'Feed',
),
BottomNavigationBarItem(
icon: new Icon(Icons.home, size: 28),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.account_circle, size: 28),
label: 'Profile'
)
],
),
tabBuilder: (BuildContext context, int index) {
return CupertinoTabView(
builder: (BuildContext context) {
return SafeArea(
top: false,
bottom: false,
child: CupertinoApp(
home: CupertinoPageScaffold(
resizeToAvoidBottomInset: false,
child: _children[_currentIndex],
),
),
);
},
);
}
);
}
void onTabTapped(int index) {
setState(() {
_currentIndex = index;
});
}
}
在首页小部件中-
onTap: () {
Navigator.of(context, rootNavigator: false).pushReplacement(MaterialPageRoute(
builder: (context) => VisionBoard(), maintainState: false));
}
我希望在从主页上单击该按钮后,可以通过单击它 return 回到主页 page/widget。现在,它似乎处于活动状态,没有任何反应。
有很多方法可以做到,但最简单的方法是这个包
persistent_bottom_nav_bar: ^4.0.2
您可以使用persistent_bottom_nav_bar来达到您的期望。操作如下:
late PersistentTabController _controller;
@override
void initState() {
super.initState();
_controller = PersistentTabController(initialIndex: 0);
}
List<PersistentBottomNavBarItem> _navBarsItems() {
return [
PersistentBottomNavBarItem(
icon: Image.asset('assets/logowhite.png', height: 30, width: 30),
inactiveIcon:
Image.asset('assets/logowhite.png', height: 30, width: 30),
title: "Vesvusa",
textStyle: const TextStyle(color: Colors.white),
activeColorPrimary: MyTheme.grey,
activeColorSecondary: Colors.white,
contentPadding: 5,
inactiveColorPrimary: Colors.white,
inactiveColorSecondary: Colors.white,
routeAndNavigatorSettings: RouteAndNavigatorSettings(
initialRoute: '/dashboard',
routes: {
'/newsevents': (context) => NewsListScreen(
menuScreenContext: context,
hideMainAppBar: hideMainAppBar,
itemCount: null),
'/blogdetails': (context) => BlogDetails(
menuScreenContext: context,
hideMainAppBar: hideMainAppBar,
),
'/videoslist': (context) => VideosList(menuScreenContext: context),
'/bookings': (context) => Bookings(menuScreenContext: context),
'/lookstheme': (context) => LooksTheme(menuScreenContext: context),
'/catalog': (context) => Catalog(menuScreenContext: context),
'/productdetails': (context) =>
ProductDetails(menuScreenContext: context),
},
),
),
PersistentBottomNavBarItem(
icon: Image.asset(
'assets/search.png',
height: 25,
width: 25,
color: Colors.white,
),
inactiveIcon: Image.asset(
'assets/search.png',
height: 25,
width: 25,
color: Colors.white,
),
title: ("Search"),
activeColorPrimary: MyTheme.grey,
activeColorSecondary: Colors.white,
contentPadding: 5,
inactiveColorPrimary: Colors.white,
inactiveColorSecondary: Colors.white,
routeAndNavigatorSettings: const RouteAndNavigatorSettings(
initialRoute: '/search',
routes: {
// '/first': (context) => MainScreen2(),
// '/second': (context) => MainScreen3(),
},
),
),
PersistentBottomNavBarItem(
icon: Image.asset(
'assets/favourite.png',
height: 25,
width: 25,
color: Colors.white,
),
inactiveIcon: Image.asset(
'assets/favourite.png',
height: 25,
width: 25,
color: Colors.white,
),
title: ("Favorite"),
activeColorPrimary: MyTheme.grey,
activeColorSecondary: Colors.white,
contentPadding: 5,
inactiveColorPrimary: Colors.white,
inactiveColorSecondary: Colors.white,
textStyle: const TextStyle(color: Colors.white),
routeAndNavigatorSettings: const RouteAndNavigatorSettings(
initialRoute: '/favorite',
routes: {
// '/first': (context) => MainScreen2(),
// '/second': (context) => MainScreen3(),
},
),
// onPressed: (context) {
// pushDynamicScreen(context,
// screen: SampleModalScreen(), withNavBar: true);
// }
),
PersistentBottomNavBarItem(
icon: Image.asset(
'assets/cart.png',
height: 25,
width: 25,
color: Colors.white,
),
inactiveIcon: Image.asset(
'assets/cart.png',
height: 25,
width: 25,
color: Colors.white,
),
title: ("Cart"),
activeColorPrimary: MyTheme.grey,
activeColorSecondary: Colors.white,
contentPadding: 5,
inactiveColorPrimary: Colors.white,
inactiveColorSecondary: Colors.white,
textStyle: const TextStyle(color: Colors.white),
routeAndNavigatorSettings: const RouteAndNavigatorSettings(
initialRoute: '/cart',
routes: {
// '/first': (context) => MainScreen2(),
// '/second': (context) => MainScreen3(),
},
),
),
PersistentBottomNavBarItem(
icon: Image.asset(
'assets/profile.png',
height: 25,
width: 25,
color: Colors.white,
),
inactiveIcon: Image.asset(
'assets/profile.png',
height: 25,
width: 25,
color: Colors.white,
),
title: ("Profile"),
activeColorPrimary: MyTheme.grey,
activeColorSecondary: Colors.white,
contentPadding: 5,
inactiveColorPrimary: Colors.white,
inactiveColorSecondary: Colors.white,
textStyle: const TextStyle(color: Colors.white),
routeAndNavigatorSettings: RouteAndNavigatorSettings(
initialRoute: '/profile',
routes: {
'/orders': (context) => MyOrders(
menuScreenContext: context,
),
'/loginsecurity': (context) => LoginSecurity(
menuScreenContext: context,
),
'/payment': (context) => Payment(
menuScreenContext: context,
),
'/message': (context) => Messages(
menuScreenContext: context,
),
'/devices': (context) => Devices(
menuScreenContext: context,
),
'/devices': (context) => Devices(
menuScreenContext: context,
),
'/inboxdetails': (context) => InboxDetails(
menuScreenContext: context,
),
'/loyalty': (context) => Loyalty(menuScreenContext: context),
},
),
),
];
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: MyTheme.themeColor,
appBar: AppBar(
elevation: 0,
iconTheme: IconThemeData(
color: MyTheme.grey,
),
centerTitle: true,
backgroundColor: MyTheme.themeColor,
title: Image.asset("assets/titles.png", height: 60, width: 100),
actions: [
Builder(
builder: (context) {
return InkWell(
onTap: () {
Scaffold.of(context).openEndDrawer();
},
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 20, 0),
child: Icon(Icons.notifications_none_outlined,
color: MyTheme.grey),
));
},
)
],
),
drawer: MyDrawer(),
endDrawer: const NotificationDrawer(),
body: PersistentTabView(
context,
controller: _controller,
screens: _buildScreens(),
items: _navBarsItems(),
confineInSafeArea: true,
backgroundColor: MyTheme.themeColor,
handleAndroidBackButtonPress: true,
resizeToAvoidBottomInset: true,
stateManagement: true,
hideNavigationBarWhenKeyboardShows: true,
margin: const EdgeInsets.all(0.0),
popActionScreens: PopActionScreensType.once,
bottomScreenMargin: 0.0,
onWillPop: (context) async {
await showDialog(
context: context!,
useSafeArea: false,
builder: (context) => CommonAlert());
return false;
},
selectedTabScreenContext: (context) {
context = context;
},
hideNavigationBar: _hideNavBar,
popAllScreensOnTapOfSelectedTab: true,
itemAnimationProperties: const ItemAnimationProperties(
duration: Duration(milliseconds: 200),
curve: Curves.ease,
),
screenTransitionAnimation: const ScreenTransitionAnimation(
animateTabTransition: true,
curve: Curves.ease,
duration: Duration(milliseconds: 200),
),
navBarStyle:
NavBarStyle.style7, // Choose the nav bar style with this property
),
);
}
您可以导航到其他页面执行此操作
pushNewScreen(context,
screen: Loyalty(
menuScreenContext: context,
),pageTransitionAnimation:PageTransitionAnimation.scale);
},
我在考虑 2 个选择:
- 使用普通的按钮导航栏,但不带导航改变页面,可以更新状态(我看到过类似的,但不推荐这种方式)
- 创建一个自定义导航栏(创建一个看起来像它的小部件),您可以将其用作 2 个页面的通用 UI 小部件(推荐)
希望我已经解决了问题。
使用persistent_bottom_nav_bar包。它为 Flutter 提供了 persistent/static 底部导航栏。
我实现了不同类型的菜单(底部导航栏、cupertino 和自定义导航栏),但没有解决问题。 我不想使用应用栏返回,只能使用菜单。 所以工作流程将是这样的:3 个按钮 - 提要、主页和个人资料。 在菜单的主页上,我将有一个按钮。当我按下那个按钮时,我想显示菜单,即使那一刻没有按钮处于活动状态。 cupertino 解决方案对我有用,但我遇到了问题。主页按钮处于活动状态,我无法返回主屏幕。
class Menu extends StatefulWidget {
const Menu({Key? key}) : super(key: key);
@override
_MenuState createState() => _MenuState();
}
class _MenuState extends State<Menu> {
int _currentIndex = 1;
final List _children = [
Feed(),
Home(),
Profile(),
];
@override
Widget build(BuildContext context) {
return CupertinoTabScaffold(
backgroundColor: Colors.transparent,
tabBar: CupertinoTabBar(
onTap: onTabTapped, // new
currentIndex: _currentIndex,
//type: BottomNavigationBarType.fixed, // Fixed
backgroundColor: Colors.white, // <-- This works for fixed
//unselectedItemColor: Color(0xff221F1E),
//selectedItemColor: Color(0xffE4BDB6),
//showSelectedLabels: false,
//showUnselectedLabels: false,
items: [
BottomNavigationBarItem(
icon: new Icon(Icons.chat_rounded, size: 28),
label: 'Feed',
),
BottomNavigationBarItem(
icon: new Icon(Icons.home, size: 28),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.account_circle, size: 28),
label: 'Profile'
)
],
),
tabBuilder: (BuildContext context, int index) {
return CupertinoTabView(
builder: (BuildContext context) {
return SafeArea(
top: false,
bottom: false,
child: CupertinoApp(
home: CupertinoPageScaffold(
resizeToAvoidBottomInset: false,
child: _children[_currentIndex],
),
),
);
},
);
}
);
}
void onTabTapped(int index) {
setState(() {
_currentIndex = index;
});
}
}
在首页小部件中-
onTap: () {
Navigator.of(context, rootNavigator: false).pushReplacement(MaterialPageRoute(
builder: (context) => VisionBoard(), maintainState: false));
}
我希望在从主页上单击该按钮后,可以通过单击它 return 回到主页 page/widget。现在,它似乎处于活动状态,没有任何反应。
有很多方法可以做到,但最简单的方法是这个包
persistent_bottom_nav_bar: ^4.0.2
您可以使用persistent_bottom_nav_bar来达到您的期望。操作如下:
late PersistentTabController _controller;
@override
void initState() {
super.initState();
_controller = PersistentTabController(initialIndex: 0);
}
List<PersistentBottomNavBarItem> _navBarsItems() {
return [
PersistentBottomNavBarItem(
icon: Image.asset('assets/logowhite.png', height: 30, width: 30),
inactiveIcon:
Image.asset('assets/logowhite.png', height: 30, width: 30),
title: "Vesvusa",
textStyle: const TextStyle(color: Colors.white),
activeColorPrimary: MyTheme.grey,
activeColorSecondary: Colors.white,
contentPadding: 5,
inactiveColorPrimary: Colors.white,
inactiveColorSecondary: Colors.white,
routeAndNavigatorSettings: RouteAndNavigatorSettings(
initialRoute: '/dashboard',
routes: {
'/newsevents': (context) => NewsListScreen(
menuScreenContext: context,
hideMainAppBar: hideMainAppBar,
itemCount: null),
'/blogdetails': (context) => BlogDetails(
menuScreenContext: context,
hideMainAppBar: hideMainAppBar,
),
'/videoslist': (context) => VideosList(menuScreenContext: context),
'/bookings': (context) => Bookings(menuScreenContext: context),
'/lookstheme': (context) => LooksTheme(menuScreenContext: context),
'/catalog': (context) => Catalog(menuScreenContext: context),
'/productdetails': (context) =>
ProductDetails(menuScreenContext: context),
},
),
),
PersistentBottomNavBarItem(
icon: Image.asset(
'assets/search.png',
height: 25,
width: 25,
color: Colors.white,
),
inactiveIcon: Image.asset(
'assets/search.png',
height: 25,
width: 25,
color: Colors.white,
),
title: ("Search"),
activeColorPrimary: MyTheme.grey,
activeColorSecondary: Colors.white,
contentPadding: 5,
inactiveColorPrimary: Colors.white,
inactiveColorSecondary: Colors.white,
routeAndNavigatorSettings: const RouteAndNavigatorSettings(
initialRoute: '/search',
routes: {
// '/first': (context) => MainScreen2(),
// '/second': (context) => MainScreen3(),
},
),
),
PersistentBottomNavBarItem(
icon: Image.asset(
'assets/favourite.png',
height: 25,
width: 25,
color: Colors.white,
),
inactiveIcon: Image.asset(
'assets/favourite.png',
height: 25,
width: 25,
color: Colors.white,
),
title: ("Favorite"),
activeColorPrimary: MyTheme.grey,
activeColorSecondary: Colors.white,
contentPadding: 5,
inactiveColorPrimary: Colors.white,
inactiveColorSecondary: Colors.white,
textStyle: const TextStyle(color: Colors.white),
routeAndNavigatorSettings: const RouteAndNavigatorSettings(
initialRoute: '/favorite',
routes: {
// '/first': (context) => MainScreen2(),
// '/second': (context) => MainScreen3(),
},
),
// onPressed: (context) {
// pushDynamicScreen(context,
// screen: SampleModalScreen(), withNavBar: true);
// }
),
PersistentBottomNavBarItem(
icon: Image.asset(
'assets/cart.png',
height: 25,
width: 25,
color: Colors.white,
),
inactiveIcon: Image.asset(
'assets/cart.png',
height: 25,
width: 25,
color: Colors.white,
),
title: ("Cart"),
activeColorPrimary: MyTheme.grey,
activeColorSecondary: Colors.white,
contentPadding: 5,
inactiveColorPrimary: Colors.white,
inactiveColorSecondary: Colors.white,
textStyle: const TextStyle(color: Colors.white),
routeAndNavigatorSettings: const RouteAndNavigatorSettings(
initialRoute: '/cart',
routes: {
// '/first': (context) => MainScreen2(),
// '/second': (context) => MainScreen3(),
},
),
),
PersistentBottomNavBarItem(
icon: Image.asset(
'assets/profile.png',
height: 25,
width: 25,
color: Colors.white,
),
inactiveIcon: Image.asset(
'assets/profile.png',
height: 25,
width: 25,
color: Colors.white,
),
title: ("Profile"),
activeColorPrimary: MyTheme.grey,
activeColorSecondary: Colors.white,
contentPadding: 5,
inactiveColorPrimary: Colors.white,
inactiveColorSecondary: Colors.white,
textStyle: const TextStyle(color: Colors.white),
routeAndNavigatorSettings: RouteAndNavigatorSettings(
initialRoute: '/profile',
routes: {
'/orders': (context) => MyOrders(
menuScreenContext: context,
),
'/loginsecurity': (context) => LoginSecurity(
menuScreenContext: context,
),
'/payment': (context) => Payment(
menuScreenContext: context,
),
'/message': (context) => Messages(
menuScreenContext: context,
),
'/devices': (context) => Devices(
menuScreenContext: context,
),
'/devices': (context) => Devices(
menuScreenContext: context,
),
'/inboxdetails': (context) => InboxDetails(
menuScreenContext: context,
),
'/loyalty': (context) => Loyalty(menuScreenContext: context),
},
),
),
];
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: MyTheme.themeColor,
appBar: AppBar(
elevation: 0,
iconTheme: IconThemeData(
color: MyTheme.grey,
),
centerTitle: true,
backgroundColor: MyTheme.themeColor,
title: Image.asset("assets/titles.png", height: 60, width: 100),
actions: [
Builder(
builder: (context) {
return InkWell(
onTap: () {
Scaffold.of(context).openEndDrawer();
},
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 20, 0),
child: Icon(Icons.notifications_none_outlined,
color: MyTheme.grey),
));
},
)
],
),
drawer: MyDrawer(),
endDrawer: const NotificationDrawer(),
body: PersistentTabView(
context,
controller: _controller,
screens: _buildScreens(),
items: _navBarsItems(),
confineInSafeArea: true,
backgroundColor: MyTheme.themeColor,
handleAndroidBackButtonPress: true,
resizeToAvoidBottomInset: true,
stateManagement: true,
hideNavigationBarWhenKeyboardShows: true,
margin: const EdgeInsets.all(0.0),
popActionScreens: PopActionScreensType.once,
bottomScreenMargin: 0.0,
onWillPop: (context) async {
await showDialog(
context: context!,
useSafeArea: false,
builder: (context) => CommonAlert());
return false;
},
selectedTabScreenContext: (context) {
context = context;
},
hideNavigationBar: _hideNavBar,
popAllScreensOnTapOfSelectedTab: true,
itemAnimationProperties: const ItemAnimationProperties(
duration: Duration(milliseconds: 200),
curve: Curves.ease,
),
screenTransitionAnimation: const ScreenTransitionAnimation(
animateTabTransition: true,
curve: Curves.ease,
duration: Duration(milliseconds: 200),
),
navBarStyle:
NavBarStyle.style7, // Choose the nav bar style with this property
),
);
}
您可以导航到其他页面执行此操作
pushNewScreen(context,
screen: Loyalty(
menuScreenContext: context,
),pageTransitionAnimation:PageTransitionAnimation.scale);
},
我在考虑 2 个选择:
- 使用普通的按钮导航栏,但不带导航改变页面,可以更新状态(我看到过类似的,但不推荐这种方式)
- 创建一个自定义导航栏(创建一个看起来像它的小部件),您可以将其用作 2 个页面的通用 UI 小部件(推荐)
希望我已经解决了问题。
使用persistent_bottom_nav_bar包。它为 Flutter 提供了 persistent/static 底部导航栏。