问题描述
请考虑以下示例,该示例旨在在 CustomScrollView
内呈现固定的标题栏(带有可能的自定义长/短文本).
Consider the following example that is intended to render a pinned title bar (with a potentially custom long/short text) inside of a CustomScrollView
.
class TitleBar extends StatelessWidget {
TitleBar(this.text);
final String text;
@override
Widget build(BuildContext context) => Text(
text,
style: TextStyle(fontSize: 30),
maxLines: 3,
overflow: TextOverflow.ellipsis,
);
}
class TitleBarDelegate extends SliverPersistentHeaderDelegate {
final String text;
TitleBarDelegate(this.text);
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) => TitleBar(text);
@override
bool shouldRebuild(TitleBarDelegate oldDelegate) => oldDelegate.text != text;
@override
double get maxExtent => ???;
@override
double get minExtent => maxExtent; // doesn't shrink
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: CustomScrollView(
slivers: [
SliverPersistentHeader(
pinned: true,
delegate: TitleBarDelegate('Potentially very long text'),
),
SliverToBoxAdapter(
child: Text("Foo " * 1000),
),
],
),
),
);
}
}
问题是:如何根据实际的 TitleBar
计算 maxExtent
.问题在于实际的 TitleBar
的大小取决于文本,因此通常可以预先计算.
The question is: How can I compute maxExtent
based on the actual TitleBar
. The problem is that the actual TitleBar
's size depends on the text and is hence to generally computable in advance.
请注意,与上面的示例相比, TitleBar
的布局也可能更复杂.因此,通常的问题是如何收缩" SliverPersistentHeaderDelegate
.
Note that TitleBar
might also have some more complex layout than it has in the example above. So the general question is how to 'shrink-wrap' an SliverPersistentHeaderDelegate
.
推荐答案
我最近遇到了同样的问题,并提出了以下脏"解决方案,假设标题仅包含具有给定文本样式的文本,并且您提供了最大宽度值.
I recently faced the same issue and came up with the following "dirty" solution, assuming the header only contains text with a given text style and you provide it with a max width value.
SliverPersistentHeaderDelegate 看起来像这样:
class SliverPersistentTitleDelegate extends SliverPersistentHeaderDelegate {
SliverPersistentTitleDelegate({
@required this.width,
@required this.text,
this.textStyle,
this.padding,
this.extend = 10
}) {
// create a text painter
final TextPainter textPainter = TextPainter(
textDirection: TextDirection.ltr,
)
..text = TextSpan(
text: text,
style: _textStyle,
);
// layout the text with the provided width, taking the horizontal padding into account
final double horizontalPadding = _padding.left + _padding.right;
textPainter.layout(maxWidth: width - horizontalPadding);
// measure minHeight and maxHeight, taking the vertical padding and text height into account
final double verticalPadding = _padding.top + _padding.bottom;
_minHeight = textPainter.height + verticalPadding;
_maxHeight = minHeight + extend;
}
final double width;
final String text;
final TextStyle textStyle;
final EdgeInsets padding;
final double extend;
double _minHeight;
double _maxHeight;
final core.ThemeProvider _themeProvider = di.get<core.ThemeProvider>();
@override
double get minExtent => _minHeight;
@override
double get maxExtent => maxHeight;
TextStyle get _textStyle => this.textStyle
?? _themeProvider
.defaultTheme
.appBarTheme
.textTheme;
EdgeInsets get _padding => padding ?? EdgeInsets.zero;
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent)
{
return Padding(
padding: _padding,
child: Text(
text,
style: _textStyle ,
),
);
}
@override
bool shouldRebuild(SliverPersistentTitleDelegate oldDelegate) {
return width != oldDelegate.width
|| text != oldDelegate.text
|| textStyle != oldDelegate.textStyle
|| padding != oldDelegate.padding
|| extend != oldDelegate.extend
|| _maxHeight != oldDelegate._maxHeight
|| _minHeight != oldDelegate._minHeight;
}
}
使用此类很简单:
return LayoutBuilder(
builder: (context, constrains) {
return CustomScrollView(
slivers: <Widget>[
SliverPersistentHeader(
pinned: false,
floating: true,
delegate: SliverPersistentTitleDelegate(
width: constrains.maxWidth,
text: "Some long dynamic title",
textStyle: titleTextStyle,
padding: EdgeInsets.only(
left: 16,
right: 16,
),
),
)
],
);
},
);
这篇关于自动计算SliverPersistentHeaderDelegate的maxExtent的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!