Content Description: Analyze the implementation of Flutter AppBar and complete GradientAppBar.
Recently, the project team decided to use Flutter to create a new App. During the development process, they encountered a need for a gradient AppBar.
That’s it, similar to AppBar in QQ:
With a UI library as powerful as Flutter, my first thought was that it could be supported, starting with the AppBar properties.
AppBar({
Key key,
this.leading,
this.automaticallyImplyLeading = true,
this.title,
this.actions,
this.flexibleSpace,
this.bottom,
this.elevation,
this.backgroundColor,
this.brightness,
this.iconTheme,
this.textTheme,
this.primary = true,
this.centerTitle,
this.titleSpacing = NavigationToolbar.kMiddleSpacing,
This toolbarOpacity = 1.0,
This bottomOpacity = 1.0,
}) : assert(automaticallyImplyLeading ! = null),
Assert (elevation = = null | | elevation > = 0.0).
assert(primary ! = null),
assert(titleSpacing ! = null),
assert(toolbarOpacity ! = null),
assert(bottomOpacity ! = null),
PreferredSize = size.fromheight (kToolbarHeight + (bottom?.
super(key: key);
Copy the code
I have a backgroundColor property,
final Color backgroundColor;
Copy the code
Cool cool, Color type. Next, take a look at the online postings.
How to add gradient color in AppBar in flutter
https://stackoverflow.com/questions/50412484/how-to-add-gradient-color-in-appbar-in-flutter
The main idea is to inherit a PreferredSize class and implement the desired effect through Container + decoration. (In the Scaffold class the appBar parameter requires an object that implements the PreferredSizeWidget.)
The code from the article is posted here
Widget build(BuildContext context) {
return new Scaffold(
appBar: new PreferredSize(
child: new Container(
padding: new EdgeInsets.only(
top: MediaQuery.of(context).padding.top
),
child: new Padding(
padding: const EdgeInsets.only(
Left: 30.0,
Top: 20.0,
Bottom: 20.0
),
child: new Text(
'Arnold Parge',
style: new TextStyle(
FontSize: 20.0.
fontWeight: FontWeight.w500,
color: Colors.white
),
),
),
decoration: new BoxDecoration(
gradient: new LinearGradient(
colors: [
Colors.red,
Colors.yellow
]
),
boxShadow: [
new BoxShadow(
color: Colors.grey[500],
BlurRadius: 20.0.
SpreadRadius: 1.0.
)
]
),
),
preferredSize: new Size(
MediaQuery.of(context).size.width,
150.0
),
),
body: new Center(
child: new Text('Hello'),
),
);
}
Copy the code
The effect of Flutter is not satisfactory. The leading and title of Flutter AppBar works well. Let’s do one ourselves!
class AppBar extends StatefulWidget implements PreferredSizeWidget
Copy the code
Appbar inherits the StatefulWidget, so let’s just look at its State -> _AppBarState.
Go straight to the return of the Build method, back to front, to see how the AppBar is implemented.
@override
Widget build(BuildContext context) {
// Omit some code, see later
.
final Brightness brightness = widget.brightness
?? appBarTheme.brightness
?? themeData.primaryColorBrightness;
final SystemUiOverlayStyle overlayStyle = brightness == Brightness.dark
? SystemUiOverlayStyle.light
: SystemUiOverlayStyle.dark;
Return Semantics(// Access_semantics
container: true,
Child: AnnotatedRegion<SystemUiOverlayStyle>(// handles theme related, status bar text color
value: overlayStyle,
Child: Material(// Material control, handles colors, shadows and other effects
color: widget.backgroundColor
?? appBarTheme.color
?? themeData.primaryColor,
elevation: widget.elevation
?? appBarTheme.elevation
?? _defaultElevation,
Child: Semantics(// Inside the child is the real content, we look inside the implementation of appBar.
explicitChildNodes: true,
child: appBar,
),
),
),
);
}
Copy the code
Returns a control that handles light and shade themes, colors, shadows, and child controls. We don’t want to use this color here.
Here the appBar is defined above:
Widget appBar = ClipRect(// Clip its Widget with rectangle
Child: CustomSingleChildLayout(// Constrain child Widgets by deleagate
Delegate: const _ToolbarContainerLayout(), // Here the layout is a wide fill, and the height is kkToolbarHeight
Child: IconTheme. Merge (// Process IconTheme
Data: appBarIconTheme,// Handle the iconTheme value based on judgment
Child: DefaultTextStyle(// Text style
Style: sideStyle, // Handle the style value by judging the passed textTheme
child: toolbar,
),
),
),
);
Copy the code
As you can see here, this is the wrapper for a toolbar, and we move on to the Toolbar:
// Here is a NavigationToolbar, and we set leading, title to use here
final Widget toolbar = NavigationToolbar(
leading: leading,
middle: title,
trailing: actions,
centerMiddle: widget._getEffectiveCenterTitle(themeData),
middleSpacing: widget.titleSpacing,
);
Copy the code
There are also some processing inside appBar, such as processing bottom, adding SafeArea, etc., which will not be expanded here
if (widget.bottom ! = null) { // bottom
appBar = Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(
child: ConstrainedBox(
constraints: const BoxConstraints(maxHeight: kToolbarHeight),
child: appBar,
),
),
Widget. BottomOpacity = = 1.0? widget.bottom : Opacity(
Opacity: const Interval(0.25, 1.0, curve: Curves. FastOutSlowIn). Transform (widget.bottomopacity),
child: widget.bottom,
),
].
);
}
// The padding applies to the toolbar and tabbar, not the flexible space.
if (widget.primary) { // SafeArea
appBar = SafeArea(
top: true,
child: appBar,
);
}
appBar = Align( // Alignment.topCenter
alignment: Alignment.topCenter,
child: appBar,
);
if (widget.flexibleSpace ! = null) {// flexibleSpace effect
appBar = Stack(
fit: StackFit.passthrough,
children: <Widget>[
widget.flexibleSpace,
appBar,
].
);
}
Copy the code
In AppBar, the colors are set in Material, and the most common Settings are set in toolbar, so the easiest way to color the Material’s Child layer is to leave the existing part unmodified.
The code is simple: copy the code for The AppBar, in this case called GradientAppBar, and modify it.
Add the initial and final values for the gradient color in the custom GradientAppBar constructor.
GradientAppBar({
.
this.gradientStart,
this.gradientEnd,
}) : assert(automaticallyImplyLeading ! = null),
.
super(key: key);
final Color gradientStart;
final Color gradientEnd;
Copy the code
Let’s copy the code for the _AppBarState class, in this case _GradientAppBarState (remember to modify the createState method).
Then wrap the child in the build method return in the modification, using the passed color as the gradient background.
Add the color gradient to the end of the build method, before return, using decoration
if (widget.gradientStart ! = null && widget.gradientEnd ! = null) {
appBar = Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [widget.gradientStart, widget.gradientEnd]),
),
child: appBar,
);
}
Copy the code
I’m going to do the Material color
return Material(
// Determine if gradient is used
color: widget.gradientStart ! = null && widget.gradientEnd ! = null
? Colors.transparent
: widget.backgroundColor ??
appBarTheme.color ??
themeData.primaryColor,
elevation: widget.elevation ?? appBarTheme.elevation ?? _defaultElevation,
Child: appBar, // Use the wrapped appBar
);
Copy the code
This gives the gradient effect.
Using GradientAppBar replaces the original GradientAppBar with GradientAppBar.
return Scaffold(
appBar: PreferredSize(
child: GradientAppBar(
gradientStart: Color(0xFF49A2FC),
gradientEnd: Color(0xFF2171F5),
title: Text(widget.title),
leading: Icon(Icons.ac_unit),
),
preferredSize: Size.fromHeight(400),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
].
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
Copy the code
Effect:
The project source code: https://github.com/loosaSH/flutter-appbar
This project will expand the SliverAppBar section later, give a star if you like
–END–
Identify the QR code, follow us