这是我用于折叠工具栏的Build方法:-
@override
Widget build(BuildContext context) {
return SafeArea(
child: CustomScrollView(
controller: controller,
slivers: <Widget>[
SliverAppBar(
pinned: true,
expandedHeight: appBarHeight,
leading: IconButton(
icon: Icon(
Icons.arrow_back_ios,
color: Colors.black,
),
onPressed: () => null,
),
floating: true,
flexibleSpace: FlexibleSpaceBar(
titlePadding: EdgeInsets.only(left:leftV , bottom:bottomV ),
title: Text(
"Title ",
style: TextStyle(
color: Colors.black,
fontSize: 16.0,
),
),
),
),
SliverList(delegate:
SliverChildBuilderDelegate((BuildContext context, int index) {
return ListTile(title: Text("Flutter / $index"));
}))
],
),
);
}
根据文档,我得到了删除填充的解决方案:-
///默认情况下,此属性的值为 ///
EdgeInsetsDirectional.only(start: 72, bottom: 16)
(如果标题是 ///不居中,否则EdgeInsetsDirectional.only(start 0, bottom: 16)
。 最终的EdgeInsetsGeometry titlePadding;
但是我得到的输出是:-
我想在应用栏完全折叠时将标题居中。
问题也已提交到github check here.
答案 0 :(得分:2)
我设法通过ScrollController
获得了解决方案。
Apache JMeter Properties Customization Guide
我使用了下一个功能:
double get _horizontalTitlePadding {
const kBasePadding = 15.0;
const kMultiplier = 0.5;
if (_scrollController.hasClients) {
if (_scrollController.offset < (kExpandedHeight / 2)) {
// In case 50%-100% of the expanded height is viewed
return kBasePadding;
}
if (_scrollController.offset > (kExpandedHeight - kToolbarHeight)) {
// In case 0% of the expanded height is viewed
return (kExpandedHeight / 2 - kToolbarHeight) * kMultiplier +
kBasePadding;
}
// In case 0%-50% of the expanded height is viewed
return (_scrollController.offset - (kExpandedHeight / 2)) * kMultiplier +
kBasePadding;
}
return kBasePadding;
}
我在SilverAppBar
titlePadding
内部使用了它:
child: Scaffold(
body: CustomScrollView(
controller: _scrollController,
slivers: <Widget>[
SliverAppBar(
pinned: true,
expandedHeight: kExpandedHeight,
flexibleSpace: FlexibleSpaceBar(
titlePadding: EdgeInsets.symmetric(
vertical: 16.0, horizontal: _horizontalTitlePadding),
只需确保在initState()
中初始化控制器:
_scrollController = ScrollController()..addListener(() => setState(() {}));
答案 1 :(得分:0)
自行找到解决方案!
将以下代码添加到您的 Sliver App Bar ......
flexibleSpace: LayoutBuilder(
builder:
(BuildContext context, BoxConstraints constraints) {
double percent =
((constraints.maxHeight - kToolbarHeight) *
100 /
(appBarHeight - kToolbarHeight));
double dx = 0;
dx = 100 - percent;
if (constraints.maxHeight == 100) {
dx = 0;
}
return Stack(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(
top: kToolbarHeight / 4, left: 0.0),
child: Transform.translate(
child: Text(
title,
style: MyTextStyle.getAppBarTextStyle(
screenUtil, appColors),
),
offset: Offset(
dx, constraints.maxHeight - kToolbarHeight),
),
),
],
);
},
),
百分比是根据滚动条计算的,并且已相应放置了动画。
答案 2 :(得分:0)
编辑:
我最终创建了a better solution,它利用了FlexibleSpaceBar中已经发生的转换。将文件从要点复制到您的项目中后,将FlexibleSpaceBar
替换为MyFlexibleSpaceBar
并提供titlePaddingTween
,例如
titlePaddingTween: EdgeInsetsTween(begin: EdgeInsets.only(left: 16.0, bottom: 16), end: EdgeInsets.only(left: 72.0, bottom: 16))
代替titlePadding。当应用栏完全展开时,补间动画将从“开始” EdgeInsets
到结束时折叠的“结束” EdgeInsets
动画。
我还添加了一个foreground
参数,该参数显示在标题和背景上方,但不会像它们一样进行转换。
原始答案:
其他答案都不错,但是它们重建了不必要的小部件。我的解决方案基于其他答案,但是只会重建ValueListenableBuilder
中的内容:
class SamplePage extends StatelessWidget {
static const _kBasePadding = 16.0;
static const kExpandedHeight = 250.0;
final ValueNotifier<double> _titlePaddingNotifier = ValueNotifier(_kBasePadding);
final _scrollController = ScrollController();
double get _horizontalTitlePadding {
const kCollapsedPadding = 60.0;
if (_scrollController.hasClients) {
return min(_kBasePadding + kCollapsedPadding,
_kBasePadding + (kCollapsedPadding * _scrollController.offset)/(kExpandedHeight - kToolbarHeight));
}
return _kBasePadding;
}
@override
Widget build(BuildContext context) {
_scrollController.addListener(() {
_titlePaddingNotifier.value = _horizontalTitlePadding;
});
return Scaffold(
body: NestedScrollView(
controller: _scrollController,
headerSliverBuilder: (context, innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
expandedHeight: kExpandedHeight,
floating: false,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
collapseMode: CollapseMode.pin,
centerTitle: false,
titlePadding: EdgeInsets.symmetric(vertical: 16, horizontal: 0),
title: ValueListenableBuilder(
valueListenable: _titlePaddingNotifier,
builder: (context, value, child) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: value),
child: Text(
"Title"),
);
},
),
background: Container(color: Colors.green)
)
),
];
},
body: Text("Body text")
),
);
}
}