我目前正在构建一个Flutter应用程序,推荐该地区的餐厅。然而,我把自己弄得一团糟。
为了组织和清洁起见,我希望我的应用程序将AppBar的代码与每个屏幕的代码分开。因此,我构建了KainAppBar.dar作为AppBar代码。如图所示:
import 'package:flutter/material.dart';
import 'package:gradient_app_bar/gradient_app_bar.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
GoogleSignIn _googleSignIn = GoogleSignIn(
signInOption: SignInOption.standard,
);
class KainAppBar extends StatelessWidget {
final String title;
KainAppBar(this.title);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: new GradientAppBar(
centerTitle: true,
title: new Text('Kain',
style: TextStyle(
fontFamily: 'Quiapo', fontSize: 36.0, fontWeight: FontWeight.w600
)),
backgroundColorStart: Colors.red[400],
backgroundColorEnd: Colors.red[900],
),
drawer: new Drawer(
child: ListView(
children: <Widget>[
new UserAccountsDrawerHeader(
decoration: BoxDecoration(
color: Colors.red[800],
),
accountName: new Text('Guest'),
accountEmail: new Text('guestemail@email.com'),
currentAccountPicture: new CircleAvatar(
backgroundImage: new NetworkImage('https://avatarfiles.alphacoders.com/848/84855.jpg'),
),
),
new ListTile(
title: new Text('Restaurants'),
leading: Icon(Icons.restaurant_menu),
onTap: (){
Navigator.of(context).pop();
Navigator.of(context).pushNamed('/restaurant_screen');
},
),
new ListTile(
title: new Text('Nearby'),
leading: Icon(Icons.near_me),
onTap: (){
Navigator.of(context).pop();
Navigator.of(context).pushNamed('/nearby_screen');
},
),
new ListTile(
title: new Text('Request Restaurant'),
leading: Icon(Icons.library_add),
onTap: (){
Navigator.of(context).pop();
Navigator.of(context).pushNamed('/request_screen');
},
),
new ListTile(
title: new Text('Settings'),
leading: Icon(Icons.settings),
onTap: (){},
),
new ListTile(
title: new Text('About'),
leading: Icon(Icons.info_outline),
onTap: (){},
),
new ListTile(
title: new Text('Logout'),
leading: Icon(Icons.power_settings_new),
onTap: (){
_googleSignIn.disconnect();
FirebaseAuth.instance.signOut().then((value) {
Navigator.of(context).pushReplacementNamed('/login');
}).catchError((e) {
print(e);
});
},
),
],
),
),
body: new Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(50.0, 160.0, 50.0, 0.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
],
),
)
],
),
);
}
}
对于我的一些屏幕,我可以毫无问题地声明它。这是home_screen.dart:的代码
class HomeScreen extends StatefulWidget {
@override
HomeScreenState createState() {
return HomeScreenState();
}
}
class HomeScreenState extends State<HomeScreen>{
@override
noSuchMethod(Invocation invocation) {
return super.noSuchMethod(invocation);
}
@override
Widget build(BuildContext context){
return new KainAppBar("Kain");
}
}
但是,对于我的restaurant_screen.dart,我遇到了一个问题。就上下文而言,restaurant_screen.dart所做的是通过TabBar显示应用程序中包含的餐厅,TabBar有三个选项(选项卡(:餐厅列表、烹饪列表和历史记录。这意味着除了AppBar之外,它还需要有一个TabBar。但是我不能把这个TabBar放在KainAppBar.dart里面,因为我只需要它显示在餐厅屏幕.dart里面。
这是我在restaurant_screen.dart:中的小部件代码
@override
Widget build(BuildContext context) {
return new Column(
children: <Widget>[
GradientAppBar(
title: KainAppBar("Kain"),
bottom: new TabBar(
labelColor: Colors.white,
controller: tController,
tabs: <Widget>[
new Tab(text: 'List'),
new Tab(text: 'Cuisine'),
new Tab(text: 'Favorites'),
],
),
),
TabBarView(
controller: tController,
children: <Widget>[
new firstpage.RestaurantList(),
new secondpage.CuisineList(),
new thirdpage.RestaurantFavorites(),
],
),
],
);
}
运行代码只会显示一个黑屏。对此有什么变通办法吗?
这是另一种方法。通过这样做,您可以根据需要自定义此应用程序栏。这样,如果你继续使用这种风格,你就不必在每一页上都重新创建它。您只需创建一次,然后在任何小部件中调用它。
类别
import 'package:flutter/material.dart';
class BaseAppBar extends StatelessWidget implements PreferredSizeWidget {
final Color backgroundColor = Colors.red;
final Text title;
final AppBar appBar;
final List<Widget> widgets;
/// you can add more fields that meet your needs
const BaseAppBar({Key key, this.title, this.appBar, this.widgets})
: super(key: key);
@override
Widget build(BuildContext context) {
return AppBar(
title: title,
backgroundColor: backgroundColor,
actions: widgets,
);
}
@override
Size get preferredSize => new Size.fromHeight(appBar.preferredSize.height);
}
在所需页面内执行
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: BaseAppBar(
title: Text('title'),
appBar: AppBar(),
widgets: <Widget>[Icon(Icons.more_vert)],
),
body: Container());
}
实现PreferredSizeWidget
并覆盖这样的方法(material.dart中的kToolbarHeight
是AppBar
使用的默认高度(。您也可以根据需要设置高度。
class NavBar extends StatelessWidget implements PreferredSizeWidget {
@override
Widget build(BuildContext context) {
return AppBar(
title: Text('Hello'),
);
}
@override
Size get preferredSize => Size.fromHeight(kToolbarHeight);
}
让我们有一个类似的widget.dart
:
import 'package:flutter/material.dart';
class ReusableWidgets {
static getAppBar(String title) {
return AppBar(
title: Text(title),
);
}
}
让我们继续使用这个类在我们所有的屏幕中获得appbar
,如下所示:
import 'package:filter_chip/widgets.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
appBar: new ReusableWidgets().getAppBar('Hello World'),
body: Text(
'Flutter Demo Home Page'),
),
);
}
}
您可以将AppBar包装成一个返回AppBar的函数。
headerNav.dart
import 'package:flutter/material.dart';
AppBar headerNav({String title}){
return AppBar(
title: Text(title),
);
}
homePage.dart
import 'package:flutter/material.dart';
import 'package:myapp/components/headerNav.dart';
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: headerNav(text:'Home Page'),
body: Container(
child: Text('Home'),
),
);
}
}
要定义自己的AppBar
,需要从PreferredSizeWidget
类实现preferredSize
。但是,如果你想保持默认大小,你可以通过创建一个内部实例来模仿原始的AppBar
,并引用它的大小,如下所示:
class MyFancyAppBar extends StatelessWidget implements PreferredSizeWidget {
final String title;
const MyFancyAppBar({Key? key, required this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
return AppBar(...);
}
static final _appBar = AppBar();
@override
Size get preferredSize => _appBar.preferredSize;
}
现场演示
如果你想在不同的文件中创建一个自定义的应用程序栏,以便共享它,你可以让你的新应用程序栏扩展它,然后将你的自定义传递给super((,在你的情况下,你的KainAppBar将扩展GradientAppBar,就像下面MyAppBar扩展appbar的方式一样。
参考编号:https://www.youtube.com/watch?v=cLbNY2nCuYw
class MyAppBar extends AppBar {
MyAppBar()
: super(
elevation: 0,
centerTitle: true,
actions: <Widget>[
IconButton(
onPressed: () {},
icon: Icon(Icons.search),
color: Colors.white,
)
]);
}
以下是创建AppBar小部件的示例
import 'package:flutter/material.dart';
class ListTitleBar extends StatefulWidget implements PreferredSizeWidget {
final String _left;
final String _right;
ListTitleBar(this._left, this._right);
@override
State<StatefulWidget> createState() => new ListTitleBarState(_left, _right);
@override
Size get preferredSize {
return new Size.fromHeight(20.0);
}
}
class ListTitleBarState extends State<ListTitleBar> {
String _leftTitle;
String _rightTitle;
ListTitleBarState(this._leftTitle, this._rightTitle);
@override
Widget build(BuildContext context) {
return new Container(
decoration: new BoxDecoration(
color: Colors.redAccent,
border: new Border.all(color: Colors.black),
),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
///Left Column Title
new Column(
children: <Widget>[
new Container(
color: Colors.redAccent,
padding: const EdgeInsets.all(10.0),
child: new Text(_leftTitle,
style: new TextStyle(
color: Colors.white,
fontSize: 18.0
),
),
)
],
),
///Right Column Title
new Column(
children: <Widget>[
new Container(
color: Colors.redAccent,
padding: const EdgeInsets.all(10.0),
child: new Text(_rightTitle,
style: new TextStyle(
color: Colors.white,
fontSize: 18.0
),
),
)
],
),
],
),
);
}
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
}
这是制作自定义应用程序栏的有效方法,您可以调用在应用的每个屏幕上自定义AppBar.dart
import 'package:flutter/material.dart';
import 'package:vector_math/vector_math.dart' as math;
import 'package:flutter_a/Screens/utils.dart';
import 'package:flutter/cupertino.dart';
class CustomAppBar extends StatefulWidget with PreferredSizeWidget {
final Size preferredSize;
CustomAppBar( {Key key})
: preferredSize = Size.fromHeight(56.0),
super(key: key);
@override
_CustomAppBarState createState() => _CustomAppBarState();
}
class _CustomAppBarState extends State<CustomAppBar> {
@override
Widget build(BuildContext context) {
return AppBar(
shadowColor: Colors.grey[200],
bottomOpacity: 1.0,
title: Text(
'YOUR CUSTOM APPBAR',
style: TextStyle(color: Colors.white, fontSize: 16),
),
actions: <Widget>[],
elevation: 0,
backgroundColor: Colors.cyan,
automaticallyImplyLeading: true,
);
}