![](/img/trans.png)
[英]How to Make Custom AppBar in Flutter Like in Hamilton flutter app?
[英]How to make an appbar universal in your flutter app
我在我的 flutter 應用程序中創建了一個AppBar
,但我想讓它通用(即我希望在我的應用程序的大多數屏幕中使用相同的AppBar
)。 我用一個名為AppBarscreen
的StatefulWidget
創建了一個新的 dart 文件,然后我返回了一個AppBar
小部件。 當我嘗試調用另一個文件中的小部件時,出現如下錯誤:
[![我下面有這些紅線][1]][1]
這是我創建的AppBarscreen
class 的代碼:
import 'package:flutter/material.dart';
class AppBarScreen extends StatefulWidget {
const AppBarScreen({super.key});
@override
State<AppBarScreen> createState() => _AppBarScreenState();
}
class _AppBarScreenState extends State<AppBarScreen> {
final GlobalKey<ScaffoldState> scaffoldkey = new GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return AppBar(
iconTheme: IconThemeData(color: Colors.black),
toolbarHeight: 70,
elevation: 0.0,
backgroundColor: Color(0xFFE5E5E5),
actions: [
SizedBox(
width: 10,
),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: 50,
width: 80,
],
),
SizedBox(
width: 90,
),
Image.asset(
"lib/assets/activity.png",
height: 30,
width: 30,
),
SizedBox(
width: 15,
),
Image.asset(
"lib/assets/notification-bing.png",
height: 30,
width: 30,
),
SizedBox(
width: 10,
),
CircleAvatar(
child: Icon(
Icons.person,
color: Colors.grey,
),
backgroundColor: Colors.grey[300],
),
SizedBox(
width: 10,
),
],
leadingWidth: 100,
leading: GestureDetector(
onTap: () => scaffoldkey.currentState!.openDrawer(),
child: Row(
children: [
SizedBox(width: 20),
Icon(Icons.menu, color: Colors.black),
],
),
),
);
}
}
這是我調用AppBarscreen
小部件的屏幕代碼:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
class Home extends StatefulWidget {
Home({Key? key}) : super(key: key);
@override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
final GlobalKey<ScaffoldState> scaffoldkey = new GlobalKey<ScaffoldState>();
final user = FirebaseAuth.instance.currentUser;
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
key: scaffoldkey,
drawer: SideMenu(),
backgroundColor: Color(0xFFE5E5E5),
appBar: AppBarScreen(),
body: Padding(
padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 20),
child: SingleChildScrollView(
child:
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Dashboard",
style: TextStyle(fontSize: 35, letterSpacing: 0.2),
),
Container(
child: Padding(
padding: const EdgeInsets.fromLTRB(8, 10, 15, 10),
child: Icon(
Icons.history,
size: 30,
color: Colors.green,
),
),
decoration: BoxDecoration(
border: Border.all(color: Colors.green, width: 2),
borderRadius: BorderRadius.circular(10),
),
)
],
),
Row(
children: [
Text(
"How are you today?",
style: TextStyle(fontSize: 18),
),
Image.asset(
"lib/assets/goodbye.png",
height: 20,
),
],
),
SizedBox(
height: 10,
),
Container(
height: 140,
child: PageView(
scrollDirection: Axis.horizontal,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: MyCards(
title: "Revenue",
rate: 0,
icon: "lib/assets/moneyrounded.png",
balance: 0,
color: Colors.green,
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: MyCards(
title: "Total Orders",
rate: 0,
icon: "lib/assets/clipboard2.png",
balance: 0,
color: Colors.blue),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: MyCards(
title: "Total Products",
rate: 0,
icon: "lib/assets/box.png",
balance: 0,
color: Colors.orange),
),
],
),
),
SizedBox(
height: 30,
),
//sales info card
SalesInfo(),
SizedBox(
height: 50,
),
//product info card
ProductInfo(),
SizedBox(
height: 50,
),
//expiry info card
ExpiryInfo(),
SizedBox(
height: 50,
),
//transaction card
TransactionsCard(),
SizedBox(
height: 30,
),
]),
),
),
),
);
}
}
請問我該如何擺脫錯誤?
為它制作一個方法,您可以在每個屏幕示例代碼中使用它。
AppBar newMethod() {
return AppBar(
iconTheme: IconThemeData(color: Colors.black),
toolbarHeight: 70,
elevation: 0.0,
backgroundColor: Color(0xFFE5E5E5),
actions: [
SizedBox(
width: 10,
),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: 50,
width: 80,
child: Image.asset("lib/assets/custigrow.png")),
],
),
SizedBox(
width: 90,
),
Image.asset(
"lib/assets/activity.png",
height: 30,
width: 30,
),
SizedBox(
width: 15,
),
Image.asset(
"lib/assets/notification-bing.png",
height: 30,
width: 30,
),
SizedBox(
width: 10,
),
CircleAvatar(
child: Icon(
Icons.person,
color: Colors.grey,
),
backgroundColor: Colors.grey[300],
),
SizedBox(
width: 10,
),
],
leadingWidth: 100,
leading: GestureDetector(
onTap: () => scaffoldkey.currentState!.openDrawer(),
child: Row(
children: [
SizedBox(width: 20),
Icon(Icons.menu, color: Colors.black),
],
),
),
);
}
無論您在appBar
中放置什么,都需要實現PreferredSizeWidget
。
例如,您可以更改AppBarScreen
以使其工作
class AppBarScreen extends StatefulWidget implements PreferredSizeWidget {
const AppBarScreen({super.key});
@override
State<AppBarScreen> createState() => _AppBarScreenState();
Size get preferredSize => Size.fromHeight(70);
}
如何在 Flutter 中將我的 AppBar 放在單獨的文件中,同時仍然顯示小部件?
因此,在您的可重用應用欄 class 實現實現 PreferredSizeWidget 並覆蓋
@override Size get preferredSize => new Size.fromHeight(appBar.preferredSize.height);
然后你就可以訪問了。
這是 AppbarScreeen 的完整代碼:
import 'package:flutter/material.dart';
class AppBarScreen extends StatefulWidget {
const AppBarScreen({super.key});
@override
State<AppBarScreen> createState() => _AppBarScreenState();
}
class _AppBarScreenState extends State<AppBarScreen> {
final GlobalKey<ScaffoldState> scaffoldkey = new GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
iconTheme: IconThemeData(color: Colors.black),
toolbarHeight: 70,
elevation: 0.0,
backgroundColor: Color(0xFFE5E5E5),
actions: [
SizedBox(
width: 10,
),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: 50,
width: 80,
child: Image.asset("lib/assets/custigrow.png")),
],
),
SizedBox(
width: 90,
),
Image.asset(
"lib/assets/activity.png",
height: 30,
width: 30,
),
SizedBox(
width: 15,
),
Image.asset(
"lib/assets/notification-bing.png",
height: 30,
width: 30,
),
SizedBox(
width: 10,
),
CircleAvatar(
child: Icon(
Icons.person,
color: Colors.grey,
),
backgroundColor: Colors.grey[300],
),
SizedBox(
width: 10,
),
],
leadingWidth: 100,
leading: GestureDetector(
onTap: () => scaffoldkey.currentState!.openDrawer(),
child: Row(
children: [
SizedBox(width: 20),
Icon(Icons.menu, color: Colors.black),
],
),
),
));
}
}
這適用於您要使用 appbarscreen class 的地方
import 'package:custigrow/Utilities/app_bar.dart';
import 'package:custigrow/Utilities/expiry_information_card.dart';
import 'package:custigrow/Utilities/my_cards.dart';
import 'package:custigrow/Utilities/product_information_card.dart';
import 'package:custigrow/Utilities/sales_information_card.dart';
import 'package:custigrow/Utilities/transactions_card.dart';
import 'package:custigrow/screens/authenticate/sign_in.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:custigrow/Utilities/side_menu.dart';
class Home extends StatefulWidget {
Home({Key? key}) : super(key: key);
@override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
final GlobalKey<ScaffoldState> scaffoldkey = new GlobalKey<ScaffoldState>();
final user = FirebaseAuth.instance.currentUser;
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
key: scaffoldkey,
drawer: SideMenu(),
backgroundColor: Color(0xFFE5E5E5),
appBar: PreferredSize(
preferredSize: Size.fromHeight(120), child: AppBarScreen()),
body: Padding(
padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 20),
child: SingleChildScrollView(
child:
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Dashboard",
style: TextStyle(fontSize: 35, letterSpacing: 0.2),
),
Container(
child: Padding(
padding: const EdgeInsets.fromLTRB(8, 10, 15, 10),
child: Icon(
Icons.history,
size: 30,
color: Colors.green,
),
),
decoration: BoxDecoration(
border: Border.all(color: Colors.green, width: 2),
borderRadius: BorderRadius.circular(10),
),
)
],
),
Row(
children: [
Text(
"How are you today?",
style: TextStyle(fontSize: 18),
),
Image.asset(
"lib/assets/goodbye.png",
height: 20,
),
],
),
SizedBox(
height: 10,
),
Container(
height: 140,
child: PageView(
scrollDirection: Axis.horizontal,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: MyCards(
title: "Revenue",
rate: 0,
icon: "lib/assets/moneyrounded.png",
balance: 0,
color: Colors.green,
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: MyCards(
title: "Total Orders",
rate: 0,
icon: "lib/assets/clipboard2.png",
balance: 0,
color: Colors.blue),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: MyCards(
title: "Total Products",
rate: 0,
icon: "lib/assets/box.png",
balance: 0,
color: Colors.orange),
),
],
),
),
SizedBox(
height: 30,
),
//sales info card
SalesInfo(),
SizedBox(
height: 50,
),
//product info card
ProductInfo(),
SizedBox(
height: 50,
),
//expiry info card
ExpiryInfo(),
SizedBox(
height: 50,
),
//transaction card
TransactionsCard(),
SizedBox(
height: 30,
),
]),
),
),
),
);
}
}
創建一個將在其中實現 AppBar 的 ParentContainer。 就像下面的代碼
class ParentContainer extends StatelessWidget {
final bool isShowLeading;
final String title;
final String toolTip;
final Widget action;
final VoidCallback callback;
final Function onAction;
final Widget body;
final int walletBalance;
ParentContainer({
this.title,
this.action,
this.onAction,
this.toolTip,
this.callback,
this.walletBalance,
this.isShowLeading = false,
@required this.body,
});
@override
Widget build(BuildContext context) {
return Scaffold(
// key: _scaffoldKey,
resizeToAvoidBottomInset: false,
backgroundColor: AppColor.appWhite,
appBar: AppBar(
elevation: 0,
toolbarHeight: 0,
leading: new IconButton(
icon: new Icon(
Icons.arrow_back,
color: AppColor.appBrightBlue,
),
onPressed: () => Navigator.of(context).pop(),
),
title: Text(
title != null ? title : "",
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 20,
color: AppColor.appBrightBlue,
fontWeight: FontWeight.bold),
),
backgroundColor: AppColor.appPrimaryColor,
centerTitle: false,
actions: <Widget>[action != null ? action : Container()],
),
body: body);
}
}
並將此 class 稱為每個 class 中的頂部小部件。 喜歡
Widget build(BuildContext context) {
return ParentContainer(
title: "Discounts",
isShowLeading: true,
body:ListView()
...
....
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.