Flutter:如何让 buttomNavigationBar 的 BottomAppBar 出现在我拥有的每个屏幕中?
Flutter : How do I make BottomAppBar of buttomNavigationBar appear in every screens I have?
我正在使用 BottomAppBar 而不是 BottomNavigationBar 小部件。我想让这个栏出现在我拥有的每个屏幕上。同样,我不想使用 BottomNavigationBar。
bottomNavigationBar: BottomAppBar(
child: Container(
height: 60,
width: width,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
// Home
MaterialButton(
onPressed: () {
setState(() {
currentScreen = HomeScreenWrapper();
currentTab = 0;
});
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.home,
color: currentTab == 0 ? primaryColor : Colors.grey,
),
Text(
AppLocalizations.of(context).translate('HOME'),
style: TextStyle(
color: currentTab == 0 ? primaryColor : Colors.grey,
fontSize: 10,
),
),
],
),
minWidth: width / 5,
),
// Dashboard
MaterialButton(
onPressed: () {
setState(() {
currentScreen = PointScreenWrapper();
currentTab = 2;
});
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SvgPicture.asset(
'assets/images/dashboard.svg',
color: currentTab == 2 ? primaryColor : null,
),
// Icon(
// // Icons.show_chart,
// Icons.dashboard,
// //Icons.crop_square,
// color: currentTab == 2 ? primaryColor : Colors.grey,
// ),
Text(
AppLocalizations.of(context).translate('DASHBOARD'),
style: TextStyle(
color: currentTab == 2 ? primaryColor : Colors.grey,
fontSize: 10,
),
),
],
),
minWidth: width / 5,
),
// //Make a dummy space between
SizedBox(
width: width / 5,
),
// Score
MaterialButton(
onPressed: () {
setState(() {
currentScreen = ChallengeScreen();
currentTab = 1;
});
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SvgPicture.asset(
'assets/images/ranking.svg',
color: currentTab == 1 ? primaryColor : Colors.grey,
),
// Icon(
// Icons.star,
// color: currentTab == 1 ? primaryColor : Colors.grey,
// size: 30,
// ),
Text(
AppLocalizations.of(context).translate('RATING'),
style: TextStyle(
color: currentTab == 1 ? primaryColor : Colors.grey,
fontSize: 10,
),
),
],
),
minWidth: width / 5,
),
//
MaterialButton(
onPressed: () {
setState(() {
currentScreen = ProfileWrapper();
currentTab = 3;
});
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SvgPicture.asset(
'assets/images/profile.svg',
color: currentTab == 3 ? primaryColor : Colors.grey,
),
// Icon(
// Icons.settings,
// color: currentTab == 3 ? primaryColor : Colors.grey,
// ),
Text(
AppLocalizations.of(context).translate('PROFILE'),
style: TextStyle(
color: currentTab == 3 ? primaryColor : Colors.grey,
fontSize: 10,
),
),
],
),
minWidth: width / 5,
),
],
),
),
shape: CircularNotchedRectangle(),
),
我该怎么做?请给我一些关于这个问题的指示。我期待着收到你们任何人的来信。提前谢谢你...
您可以复制粘贴 运行 下面的完整代码
您可以在单击 MaterialButton
时使用 PageView
使用 index
调用 bottomTapped
代码片段
Widget buildPageView() {
return PageView(
controller: pageController,
onPageChanged: (index) {
pageChanged(index);
},
children: <Widget>[
Red(),
Blue(),
Yellow(),
Green(),
],
);
}
@override
void initState() {
super.initState();
}
void pageChanged(int index) {
setState(() {
currentTab = index;
});
}
void bottomTapped(int index) {
setState(() {
currentTab = index;
pageController.animateToPage(index,
duration: Duration(milliseconds: 500), curve: Curves.ease);
});
}
工作演示
完整代码
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
double width;
Color primaryColor = Colors.blue;
int currentTab = 0;
PageController pageController = PageController(
initialPage: 0,
keepPage: true,
);
Widget buildPageView() {
return PageView(
controller: pageController,
onPageChanged: (index) {
pageChanged(index);
},
children: <Widget>[
Red(),
Blue(),
Yellow(),
Green(),
],
);
}
@override
void initState() {
super.initState();
}
void pageChanged(int index) {
setState(() {
currentTab = index;
});
}
void bottomTapped(int index) {
setState(() {
currentTab = index;
pageController.animateToPage(index,
duration: Duration(milliseconds: 500), curve: Curves.ease);
});
}
@override
Widget build(BuildContext context) {
width = MediaQuery.of(context).size.width;
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: buildPageView(),
bottomNavigationBar: BottomAppBar(
child: Container(
height: 60,
width: width,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
// Home
MaterialButton(
onPressed: () {
bottomTapped(0);
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.home,
color: currentTab == 0 ? primaryColor : Colors.grey,
),
Text(
'HOME',
style: TextStyle(
color: currentTab == 0 ? primaryColor : Colors.grey,
fontSize: 10,
),
),
],
),
minWidth: width / 5,
),
// Dashboard
MaterialButton(
onPressed: () {
bottomTapped(1);
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.network(
'https://picsum.photos/20/20?image=9',
color: currentTab == 1 ? primaryColor : null,
),
// Icon(
// // Icons.show_chart,
// Icons.dashboard,
// //Icons.crop_square,
// color: currentTab == 2 ? primaryColor : Colors.grey,
// ),
Text(
'DASHBOARD',
style: TextStyle(
color: currentTab == 1 ? primaryColor : Colors.grey,
fontSize: 10,
),
),
],
),
minWidth: width / 5,
),
// //Make a dummy space between
SizedBox(
width: width / 10,
),
// Score
MaterialButton(
onPressed: () {
bottomTapped(2);
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.network(
'https://picsum.photos/20/20?image=9',
color: currentTab == 2 ? primaryColor : Colors.grey,
),
// Icon(
// Icons.star,
// color: currentTab == 1 ? primaryColor : Colors.grey,
// size: 30,
// ),
Text(
'RATING',
style: TextStyle(
color: currentTab == 2 ? primaryColor : Colors.grey,
fontSize: 10,
),
),
],
),
minWidth: width / 5,
),
//
MaterialButton(
onPressed: () {
bottomTapped(3);
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.network(
'https://picsum.photos/20/20?image=9',
color: currentTab == 3 ? primaryColor : Colors.grey,
),
// Icon(
// Icons.settings,
// color: currentTab == 3 ? primaryColor : Colors.grey,
// ),
Text(
'PROFILE',
style: TextStyle(
color: currentTab == 3 ? primaryColor : Colors.grey,
fontSize: 10,
),
),
],
),
minWidth: width / 5,
),
],
),
),
shape: CircularNotchedRectangle(),
),
);
}
}
class Red extends StatefulWidget {
@override
_RedState createState() => _RedState();
}
class _RedState extends State<Red> {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
);
}
}
class Blue extends StatefulWidget {
@override
_BlueState createState() => _BlueState();
}
class _BlueState extends State<Blue> {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.blueAccent,
);
}
}
class Yellow extends StatefulWidget {
@override
_YellowState createState() => _YellowState();
}
class _YellowState extends State<Yellow> {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.yellowAccent,
);
}
}
class Green extends StatefulWidget {
@override
_GreenState createState() => _GreenState();
}
class _GreenState extends State<Green> {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.greenAccent,
);
}
}
@Eren 是对的,你不能在每个屏幕上使用相同的小部件,因为它是 Scaffold 字段的范围,所以它反对颤振物理,但你可以对每个页面使用 Common bottom-sheet class 并传递它页面上下文。
在 flutter 中,一个好的做法是创建一个小部件并在每个脚手架中使用它。这是我在我的应用程序中使用的示例代码
import 'package:flutter/material.dart';
class AppBottomNavigationBar extends StatelessWidget {
final int selectedIndex;
const AppBottomNavigationBar({
Key key,
@required this.selectedIndex,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: Icon(Icons.mail_outline),
title: Text('Messages'),
),
BottomNavigationBarItem(
icon: Icon(Icons.explore),
title: Text('Explore'),
),
BottomNavigationBarItem(
icon: Icon(Icons.person_outline),
title: Text('Profile'),
),
],
currentIndex: selectedIndex,
onTap: (int index) {
if (selectedIndex == index) {
return;
}
if (index == 0) {
Navigator.of(context).pushReplacementNamed('/home');
} else if (index == 1) {
Navigator.of(context).pushReplacementNamed('/messages');
} else if (index == 2) {
Navigator.of(context).pushReplacementNamed('/explore');
} else if (index == 3) {
Navigator.of(context).pushReplacementNamed('/profile');
}
},
);
}
}
我正在使用 BottomAppBar 而不是 BottomNavigationBar 小部件。我想让这个栏出现在我拥有的每个屏幕上。同样,我不想使用 BottomNavigationBar。
bottomNavigationBar: BottomAppBar(
child: Container(
height: 60,
width: width,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
// Home
MaterialButton(
onPressed: () {
setState(() {
currentScreen = HomeScreenWrapper();
currentTab = 0;
});
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.home,
color: currentTab == 0 ? primaryColor : Colors.grey,
),
Text(
AppLocalizations.of(context).translate('HOME'),
style: TextStyle(
color: currentTab == 0 ? primaryColor : Colors.grey,
fontSize: 10,
),
),
],
),
minWidth: width / 5,
),
// Dashboard
MaterialButton(
onPressed: () {
setState(() {
currentScreen = PointScreenWrapper();
currentTab = 2;
});
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SvgPicture.asset(
'assets/images/dashboard.svg',
color: currentTab == 2 ? primaryColor : null,
),
// Icon(
// // Icons.show_chart,
// Icons.dashboard,
// //Icons.crop_square,
// color: currentTab == 2 ? primaryColor : Colors.grey,
// ),
Text(
AppLocalizations.of(context).translate('DASHBOARD'),
style: TextStyle(
color: currentTab == 2 ? primaryColor : Colors.grey,
fontSize: 10,
),
),
],
),
minWidth: width / 5,
),
// //Make a dummy space between
SizedBox(
width: width / 5,
),
// Score
MaterialButton(
onPressed: () {
setState(() {
currentScreen = ChallengeScreen();
currentTab = 1;
});
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SvgPicture.asset(
'assets/images/ranking.svg',
color: currentTab == 1 ? primaryColor : Colors.grey,
),
// Icon(
// Icons.star,
// color: currentTab == 1 ? primaryColor : Colors.grey,
// size: 30,
// ),
Text(
AppLocalizations.of(context).translate('RATING'),
style: TextStyle(
color: currentTab == 1 ? primaryColor : Colors.grey,
fontSize: 10,
),
),
],
),
minWidth: width / 5,
),
//
MaterialButton(
onPressed: () {
setState(() {
currentScreen = ProfileWrapper();
currentTab = 3;
});
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SvgPicture.asset(
'assets/images/profile.svg',
color: currentTab == 3 ? primaryColor : Colors.grey,
),
// Icon(
// Icons.settings,
// color: currentTab == 3 ? primaryColor : Colors.grey,
// ),
Text(
AppLocalizations.of(context).translate('PROFILE'),
style: TextStyle(
color: currentTab == 3 ? primaryColor : Colors.grey,
fontSize: 10,
),
),
],
),
minWidth: width / 5,
),
],
),
),
shape: CircularNotchedRectangle(),
),
我该怎么做?请给我一些关于这个问题的指示。我期待着收到你们任何人的来信。提前谢谢你...
您可以复制粘贴 运行 下面的完整代码
您可以在单击 MaterialButton
时使用 PageView
使用 index
调用 bottomTapped
代码片段
Widget buildPageView() {
return PageView(
controller: pageController,
onPageChanged: (index) {
pageChanged(index);
},
children: <Widget>[
Red(),
Blue(),
Yellow(),
Green(),
],
);
}
@override
void initState() {
super.initState();
}
void pageChanged(int index) {
setState(() {
currentTab = index;
});
}
void bottomTapped(int index) {
setState(() {
currentTab = index;
pageController.animateToPage(index,
duration: Duration(milliseconds: 500), curve: Curves.ease);
});
}
工作演示
完整代码
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
double width;
Color primaryColor = Colors.blue;
int currentTab = 0;
PageController pageController = PageController(
initialPage: 0,
keepPage: true,
);
Widget buildPageView() {
return PageView(
controller: pageController,
onPageChanged: (index) {
pageChanged(index);
},
children: <Widget>[
Red(),
Blue(),
Yellow(),
Green(),
],
);
}
@override
void initState() {
super.initState();
}
void pageChanged(int index) {
setState(() {
currentTab = index;
});
}
void bottomTapped(int index) {
setState(() {
currentTab = index;
pageController.animateToPage(index,
duration: Duration(milliseconds: 500), curve: Curves.ease);
});
}
@override
Widget build(BuildContext context) {
width = MediaQuery.of(context).size.width;
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: buildPageView(),
bottomNavigationBar: BottomAppBar(
child: Container(
height: 60,
width: width,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
// Home
MaterialButton(
onPressed: () {
bottomTapped(0);
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.home,
color: currentTab == 0 ? primaryColor : Colors.grey,
),
Text(
'HOME',
style: TextStyle(
color: currentTab == 0 ? primaryColor : Colors.grey,
fontSize: 10,
),
),
],
),
minWidth: width / 5,
),
// Dashboard
MaterialButton(
onPressed: () {
bottomTapped(1);
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.network(
'https://picsum.photos/20/20?image=9',
color: currentTab == 1 ? primaryColor : null,
),
// Icon(
// // Icons.show_chart,
// Icons.dashboard,
// //Icons.crop_square,
// color: currentTab == 2 ? primaryColor : Colors.grey,
// ),
Text(
'DASHBOARD',
style: TextStyle(
color: currentTab == 1 ? primaryColor : Colors.grey,
fontSize: 10,
),
),
],
),
minWidth: width / 5,
),
// //Make a dummy space between
SizedBox(
width: width / 10,
),
// Score
MaterialButton(
onPressed: () {
bottomTapped(2);
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.network(
'https://picsum.photos/20/20?image=9',
color: currentTab == 2 ? primaryColor : Colors.grey,
),
// Icon(
// Icons.star,
// color: currentTab == 1 ? primaryColor : Colors.grey,
// size: 30,
// ),
Text(
'RATING',
style: TextStyle(
color: currentTab == 2 ? primaryColor : Colors.grey,
fontSize: 10,
),
),
],
),
minWidth: width / 5,
),
//
MaterialButton(
onPressed: () {
bottomTapped(3);
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.network(
'https://picsum.photos/20/20?image=9',
color: currentTab == 3 ? primaryColor : Colors.grey,
),
// Icon(
// Icons.settings,
// color: currentTab == 3 ? primaryColor : Colors.grey,
// ),
Text(
'PROFILE',
style: TextStyle(
color: currentTab == 3 ? primaryColor : Colors.grey,
fontSize: 10,
),
),
],
),
minWidth: width / 5,
),
],
),
),
shape: CircularNotchedRectangle(),
),
);
}
}
class Red extends StatefulWidget {
@override
_RedState createState() => _RedState();
}
class _RedState extends State<Red> {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
);
}
}
class Blue extends StatefulWidget {
@override
_BlueState createState() => _BlueState();
}
class _BlueState extends State<Blue> {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.blueAccent,
);
}
}
class Yellow extends StatefulWidget {
@override
_YellowState createState() => _YellowState();
}
class _YellowState extends State<Yellow> {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.yellowAccent,
);
}
}
class Green extends StatefulWidget {
@override
_GreenState createState() => _GreenState();
}
class _GreenState extends State<Green> {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.greenAccent,
);
}
}
@Eren 是对的,你不能在每个屏幕上使用相同的小部件,因为它是 Scaffold 字段的范围,所以它反对颤振物理,但你可以对每个页面使用 Common bottom-sheet class 并传递它页面上下文。
在 flutter 中,一个好的做法是创建一个小部件并在每个脚手架中使用它。这是我在我的应用程序中使用的示例代码
import 'package:flutter/material.dart';
class AppBottomNavigationBar extends StatelessWidget {
final int selectedIndex;
const AppBottomNavigationBar({
Key key,
@required this.selectedIndex,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: Icon(Icons.mail_outline),
title: Text('Messages'),
),
BottomNavigationBarItem(
icon: Icon(Icons.explore),
title: Text('Explore'),
),
BottomNavigationBarItem(
icon: Icon(Icons.person_outline),
title: Text('Profile'),
),
],
currentIndex: selectedIndex,
onTap: (int index) {
if (selectedIndex == index) {
return;
}
if (index == 0) {
Navigator.of(context).pushReplacementNamed('/home');
} else if (index == 1) {
Navigator.of(context).pushReplacementNamed('/messages');
} else if (index == 2) {
Navigator.of(context).pushReplacementNamed('/explore');
} else if (index == 3) {
Navigator.of(context).pushReplacementNamed('/profile');
}
},
);
}
}