I'm trying to create a reusable app bar that has a dynamic size. I am using dynamic values to adjust the size of icons, padding, text font size, etc in the app and want to do the same with the app bar size. The app bar code below works dynamically and gives me the behavior I want using MediaQuery.
class SamplePage extends StatelessWidget {
const SamplePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final screenHeight = MediaQuery.of(context).size.height;
return Scaffold(
appBar: AppBar(
actions: const [
BrandPopUpMenu(),
],
automaticallyImplyLeading: true,
centerTitle: true,
title: const AppBarText(
pageName: PageName.nutrition,
),
toolbarHeight: screenHeight / 15.07,
),
drawer: const SideSheet(),
body: Container(),
);
}
}
When I try to create a reusable app bar from the code above that is when I run into trouble.
class SamplePage extends StatelessWidget {
const SamplePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final screenHeight = MediaQuery.of(context).size.height;
return Scaffold(
appBar: SamplePageDynamicAppBar(screenHeight: screenHeight),
drawer: const SideSheet(),
body: Container(),
);
}
}
The code below only works with a hard coded preferred size and I am uncertain how to continue to use the dynamic value in the toolBarHeight and not the preferred size in the override.
class SamplePageDynamicAppBar extends StatelessWidget
implements PreferredSizeWidget {
const SamplePageDynamicAppBar({
Key? key,
required this.screenHeight,
}) : super(key: key);
final double screenHeight;
@override
Size get preferredSize => const Size.fromHeight(56.0);
@override
Widget build(BuildContext context) {
return AppBar(
actions: const [
BrandPopUpMenu(),
],
automaticallyImplyLeading: true,
centerTitle: true,
title: const AppBarText(
pageName: PageName.nutrition,
),
toolbarHeight: screenHeight / 15.07,
);
}
}
Any help will be greatly appreciated. Thanks
CodePudding user response:
Since all you're doing is overriding toolbarHeight property of AppBar, see if this works. It extends AppBar instead creating a new widget. https://dartpad.dev/?id=d15b4d91168e13b89e86267da4311683
class SamplePageDynamicAppBar extends AppBar {
SamplePageDynamicAppBar({Key? key, required double screenHeight}) :
super(
actions: const [
BrandPopUpMenu(),
],
automaticallyImplyLeading: true,
centerTitle: true,
title: const AppBarText(
pageName: PageName.nutrition,
),
toolbarHeight: screenHeight / 15.07,
);
}
Alternatively you can use the code you've written by changing your implementation of the perferredSize getter. https://dartpad.dev/?id=758db4b7a7b2908b166a6a29d766045d
class SamplePageDynamicAppBar extends StatelessWidget implements PreferredSizeWidget {
const SamplePageDynamicAppBar({
Key? key,
required double screenHeight,
}) :
toolbarHeight = screenHeight / 15.07,
super(key: key);
final double toolbarHeight;
@override
Size get preferredSize => Size.fromHeight(toolbarHeight);
@override
Widget build(BuildContext context) {
return AppBar(
actions: const [
BrandPopUpMenu(),
],
automaticallyImplyLeading: true,
centerTitle: true,
title: const AppBarText(
pageName: PageName.nutrition,
),
toolbarHeight: toolbarHeight,
);
}
}
CodePudding user response:
Try wrapping your custom AppBar
with a PreferredSize
widget when you reference it in your scaffold
as follows, not passing through your preferred height and rather declaring it as part of the PreferredSize
widget:
class SamplePage extends StatelessWidget {
const SamplePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final screenHeight = MediaQuery.of(context).size.height;
return PreferredSize(
preferredSize: Size.fromHeight(screenHeight / 15.07),
child: Scaffold(
appBar: SamplePageDynamicAppBar(),
drawer: const SideSheet(),
body: Container(),
),
);
}
}