Flutter:FlexibleSpaceBar折叠时更改文本
Posted
技术标签:
【中文标题】Flutter:FlexibleSpaceBar折叠时更改文本【英文标题】:Flutter: Change text when FlexibleSpaceBar is collapsed 【发布时间】:2018-11-27 07:39:02 【问题描述】:我查看了 Flutter 文档,试图找到一个事件、回调,甚至是当 FlexibleSpaceBar 折叠或展开时我可以挂钩的状态。
return new FlexibleSpaceBar(
title: new Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new Text(_name, style: textTheme.headline),
new Text(_caption, style: textTheme.caption)
]),
centerTitle: false,
background: getImage());`
当 FlexibleSpaceBar 卡入(折叠)时,我想隐藏 _caption 文本,只显示 _name 文本。当它完全展开时,我显然想同时显示 _name 和 _caption。
我该怎么做?
我是新来的,所以我对此有些迷茫。
也报告于https://github.com/flutter/flutter/issues/18567
【问题讨论】:
【参考方案1】:FlexibleSpaceBar
本身还不够。您需要将其包装成CustomScrollView
和SliverAppBar
。这些小部件必须由ScrollController
控制,只要滚动偏移发生变化,就会触发一个事件。根据它,您可以了解应用栏是折叠还是展开,并相应地更改内容。 Here 你会找到一个可行的例子。
【讨论】:
您也可以查看此问题了解更多详细信息。 ***.com/questions/49942791/…【参考方案2】:可以这样做:
在您的 initState
方法中添加这样的滚动侦听器:
ScrollController _controller;
bool silverCollapsed = false;
String myTitle = "default title";
@override
void initState()
super.initState();
_controller = ScrollController();
_controller.addListener(()
if (_controller.offset > 220 && !_controller.position.outOfRange)
if(!silverCollapsed)
// do what ever you want when silver is collapsing !
myTitle = "silver collapsed !";
silverCollapsed = true;
setState(() );
if (_controller.offset <= 220 && !_controller.position.outOfRange)
if(silverCollapsed)
// do what ever you want when silver is expanding !
myTitle = "silver expanded !";
silverCollapsed = false;
setState(() );
);
然后将您的 silverAppBar 包裹在 CustomScrollView
中,然后像这样将控制器添加到 CustomScrollView
中:
@override
Widget build(BuildContext context)
return Scaffold(
backgroundColor: Colors.white,
body: CustomScrollView(
controller: _controller,
slivers: <Widget>[
SliverAppBar(
expandedHeight: 300,
title: myTitle,
flexibleSpace: FlexibleSpaceBar(),
),
SliverList(
delegate: SliverChildListDelegate(<Widget>[
// your widgets inside here !
]),
),
],
),
);
最后更改条件值_controller.offset > 220
以满足您的需要!
【讨论】:
【参考方案3】:在 FlexibleSpaceBar 中指定填充高度
flexibleSpace: FlexibleSpaceBar(
titlePadding: EdgeInsets.only(
top: 100, // give the value
title: Text(
"Test"
),
【讨论】:
【参考方案4】:创建自己的 FlexibleSpaceBar 并不难。
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main()
runApp(MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: SafeArea(
child: MyHomePage(),
),
),
);
class MyHomePage extends StatefulWidget
@override
_MyHomePageState createState() => _MyHomePageState();
class _MyHomePageState extends State<MyHomePage>
ScrollController controller = ScrollController();
@override
Widget build(BuildContext context)
return CustomScrollView(
physics: ClampingScrollPhysics(),
controller: controller,
slivers: [
SliverAppBar(
expandedHeight: 220.0,
floating: true,
pinned: true,
elevation: 50,
backgroundColor: Colors.pink,
leading: IconButton(
icon: Icon(Icons.menu),
onPressed: () ,
),
flexibleSpace: _MyAppSpace(),
),
SliverList(
delegate: SliverChildListDelegate(
List.generate(
200,
(index) => Card(
child: Padding(
padding: EdgeInsets.all(10),
child: Text('text $index'),
),
),
),
),
)
],
);
class _MyAppSpace extends StatelessWidget
const _MyAppSpace(Key key) : super(key: key);
@override
Widget build(BuildContext context)
return LayoutBuilder(
builder: (context, c)
final settings = context
.dependOnInheritedWidgetOfExactType<FlexibleSpaceBarSettings>();
final deltaExtent = settings.maxExtent - settings.minExtent;
final t =
(1.0 - (settings.currentExtent - settings.minExtent) / deltaExtent)
.clamp(0.0, 1.0) as double;
final fadeStart = math.max(0.0, 1.0 - kToolbarHeight / deltaExtent);
const fadeEnd = 1.0;
final opacity = 1.0 - Interval(fadeStart, fadeEnd).transform(t);
return Stack(
children: [
Center(
child: Opacity(
opacity: 1 - opacity,
child: getTitle(
'Collapsed Title',
)),
),
Opacity(
opacity: opacity,
child: Stack(
alignment: Alignment.bottomCenter,
children: [
getImage(),
getTitle(
'Expended Title',
)
],
),
),
],
);
,
);
Widget getImage()
return Container(
width: double.infinity,
child: Image.network(
'https://source.unsplash.com/daily?code',
fit: BoxFit.cover,
),
);
Widget getTitle(String text)
return Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
text,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 26.0,
fontWeight: FontWeight.bold,
),
),
);
【讨论】:
【参考方案5】:您可以使用 AnimatedOpacity 类。
flexibleSpace: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints)
var top = constraints.biggest.height;
return FlexibleSpaceBar(
title: AnimatedOpacity(
duration: Duration(milliseconds: 300),
//opacity: top > 71 && top < 91 ? 1.0 : 0.0,
child: Text(
top > 71 && top < 91 ? "Collapse" : "Expanded",
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
)),
background: Image.network(
"https://images.ctfassets.net/pjshm78m9jt4/383122_header/d79a41045d07d114941f7641c83eea6d/importedImage383122_header",
fit: BoxFit.cover,
));
),
可以从此链接查看原始答案https://***.com/a/53380630/9719695
【讨论】:
哇,兄弟,你节省了我的时间 我只会将AnimatedOpacity
包裹在LayoutBuilder
中,以防止图像在每次构建时重新渲染。谢谢;-)【参考方案6】:
跟进 Vishnu Suresh 的回答:
flexibleSpace: FlexibleSpaceBar(
titlePadding: EdgeInsets.only(
top: kToolbarHeight, // give the value
title: Text(
"Test"
),
这将使用 appbar 高度作为填充。
【讨论】:
以上是关于Flutter:FlexibleSpaceBar折叠时更改文本的主要内容,如果未能解决你的问题,请参考以下文章
如何修改 Sliverappbar 以便在向上滚动时可以看到带有 FlexibleSpaceBar 的背景图像?
Flutter图表库fl_chart的使用解析(二)-折线图