The SliverAppBar has an attribute bottom which has to have preferredSize.
Right now I have it returning constant value:
...
new SliverAppBar(
expandedHeight: _kFlexibleSpaceMaxHeight,
flexibleSpace: new FlexibleSpaceBar(.....)
...
bottom: new BottomBar(...), // has to have preferredSize
),
...
class BottomBar extends StatelessWidget implements PreferredSizeWidget {
...
@override
Size get preferredSize {
return new Size.fromHeight(my_constant_height_value);
}
...
}
I want to put a Text inside this bottom Widget and I don't know how long the text inside it is going to be.
How can I achieve the dynamic height of the bottom widget ?
Is there a way to measure a widget's height before it is layed out ?
EDIT 25/04/2018
Eventually, I followed Thibault's instructions and ended up with this:
// 'as rendering' to avoid conflict with 'package:intl/intl.dart'
import 'package:flutter/rendering.dart' as rendering;
...
// this is the function that returns the height of a Text widget
// given the text
double getHeight(String text, BuildContext context, bool isTitle) {
var rp = rendering.RenderParagraph(
new TextSpan(
style: isTitle
? Theme.of(context).primaryTextTheme.title
: Theme.of(context).primaryTextTheme.subhead,
text: text,
children: null,
recognizer: null),
// important as the user can have increased text on his device
textScaleFactor: MediaQuery.of(context).textScaleFactor,
textDirection: rendering.TextDirection.ltr,
);
var horizontalPaddingSum = 20; // optional
var width = MediaQuery.of(context).size.width - horizontalPaddingSum;
// if your Text widget has horizontal padding then you have to
// subtract it from available width to get the needed results
var ret = rp.computeMinIntrinsicHeight(width);
return ret;
}
...
_kPreferredBBTextHeight =
getHeight(mTitle ?? "", context, true);
var verticalPaddingSum = 10;
_kPreferredBBSubTextHeight = getHeight(mSubtitle ?? "", context,false) + verticalPaddingSum;
_kPreferredBottomBarSize =
_kPreferredBBTextHeight + _kPreferredBBSubTextHeight + 48;
_kFlexibleSpaceMaxHeight =
_kPreferredBottomBarSize + _kPreferredBottomBarSize + kToolbarHeight;
_backgroudBottomPadding = _kPreferredBottomBarSize;
...
new CustomSliverAppBar(
pinned: true,
automaticallyImplyLeading: false,
primary: true,
expandedHeight: _kFlexibleSpaceMaxHeight,
flexibleSpace: new FlexibleSpaceBar(
background: new Padding(
padding:
new EdgeInsets.only(bottom: _backgroudBottomPadding),
child: new Image(
image: new NetworkImage(mImageUrl),
fit: BoxFit.cover,
)),
),
bottom: new BottomBar(
fixedHeight: _kPreferredBottomBarSize,
),
),
...
class BottomBar extends StatelessWidget implements PreferredSizeWidget {
final double fixedHeight;
BottomBar({this.fixedHeight});
@override
Size get preferredSize {
return new Size.fromHeight(this.fixedHeight);
}
@override
Widget build(BuildContext context) {
// https://github.com/flutter/flutter/issues/3782
return new Container(
height: this.fixedHeight,
child: new Material(
color: Theme.of(context).primaryColor,
child: new Column(
children: <Widget>[
new Row(
children: <Widget>[
new IconButton(
icon: new Icon(Icons.arrow_back, color: Colors.white),
onPressed: () {
Navigator.of(context).pop();
},
),
new Expanded(
child: new Container(),
),
new IconButton(
icon: new Icon(Icons.share, color: Colors.white),
onPressed: () {
print("share pressed");
},
)
],
),
new Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new Padding(
padding: new EdgeInsets.only(left: 10.0, right: 10.0),
child: new Container(
child: new Container(
alignment: Alignment.centerLeft,
child: new Text(
mTitle ?? "",
style: Theme.of(context).primaryTextTheme.title,
),
),
)),
new Container(
padding: new EdgeInsets.only(
left: 10.0, right: 10.0, top: 5.0, bottom: 5.0),
alignment: Alignment.centerLeft,
child: new Text(
mSubtitle ?? "",
style: Theme.of(context).primaryTextTheme.subhead,
),
),
],
),
],
)));
}