在 Flutter 中使用 NotificationListener 为自定义 Appbar 设置动画
Animate Custom Appbar with NotificationListener in Flutter
我想使用 NotificationListener 和 ScrollController 在 Flutter 中为 AppBar 的高度设置动画,但它似乎不起作用。我知道我遗漏了一些东西,我需要帮助来解决它。
这是我的,
class SampleApp extends StatefulWidget {
@override
_SampleAppState createState() => _SampleAppState();
}
class _SampleAppState extends State<SampleApp> with TickerProviderStateMixin {
Animation<double> animation;
AnimationController _controller;
ScrollController _scrollController;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: Duration(milliseconds: 240));
animation = Tween(begin: kToolbarHeight, end: 0.0).animate(_controller);
_scrollController = ScrollController();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
child: Container(color: Colors.red),
preferredSize: Size.fromHeight(animation.value),
),
bottomNavigationBar: Container(height: animation.value, color: Colors.red),
floatingActionButton: Container(
width: 50.0,
height: 50.0,
child: Center(
child: FittedBox(
child: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.arrow_upward),
),
),
),
),
body: NotificationListener(
onNotification: (notification) {
if (_scrollController.position.userScrollDirection == ScrollDirection.reverse) {
_controller.forward();
return true;
}
if (_scrollController.position.userScrollDirection == ScrollDirection.forward) {
_controller.reverse();
return true;
}
return false;
},
child: ListView(
controller: _scrollController,
children: List.generate(
200,
(index) => ListTile(
title: Text(index.toString()),
),
),
),
),
);
}
}
应该是如果用户向下滚动,我希望应用栏高度和底部栏高度动画化(减少) &反之亦然,如果用户 向上滚动 。
您可以复制粘贴运行下面的完整代码
您需要以下
animation.addListener(() {
setState(() {});
});
工作演示
完整代码
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,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: SampleApp(),
);
}
}
class SampleApp extends StatefulWidget {
@override
_SampleAppState createState() => _SampleAppState();
}
class _SampleAppState extends State<SampleApp> with TickerProviderStateMixin {
Animation<double> animation;
AnimationController _controller;
ScrollController _scrollController;
@override
void initState() {
super.initState();
print("$kToolbarHeight");
_controller =
AnimationController(vsync: this, duration: Duration(milliseconds: 240));
animation = Tween(begin: kToolbarHeight, end: 0.0).animate(_controller);
_scrollController = ScrollController();
animation.addListener(() {
setState(() {});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
child: Container(color: Colors.red),
preferredSize: Size.fromHeight(animation.value),
),
bottomNavigationBar:
Container(height: animation.value, color: Colors.red),
floatingActionButton: Container(
width: 50.0,
height: 50.0,
child: Center(
child: FittedBox(
child: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.arrow_upward),
),
),
),
),
body: NotificationListener(
onNotification: (notification) {
if (_scrollController.position.userScrollDirection ==
ScrollDirection.reverse) {
print("reverse");
_controller.forward();
return true;
}
if (_scrollController.position.userScrollDirection ==
ScrollDirection.forward) {
print("forward");
_controller.reverse();
return true;
}
return false;
},
child: ListView(
controller: _scrollController,
children: List.generate(
200,
(index) => ListTile(
title: Text(index.toString()),
),
),
),
),
);
}
}
我想使用 NotificationListener 和 ScrollController 在 Flutter 中为 AppBar 的高度设置动画,但它似乎不起作用。我知道我遗漏了一些东西,我需要帮助来解决它。
这是我的,
class SampleApp extends StatefulWidget {
@override
_SampleAppState createState() => _SampleAppState();
}
class _SampleAppState extends State<SampleApp> with TickerProviderStateMixin {
Animation<double> animation;
AnimationController _controller;
ScrollController _scrollController;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: Duration(milliseconds: 240));
animation = Tween(begin: kToolbarHeight, end: 0.0).animate(_controller);
_scrollController = ScrollController();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
child: Container(color: Colors.red),
preferredSize: Size.fromHeight(animation.value),
),
bottomNavigationBar: Container(height: animation.value, color: Colors.red),
floatingActionButton: Container(
width: 50.0,
height: 50.0,
child: Center(
child: FittedBox(
child: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.arrow_upward),
),
),
),
),
body: NotificationListener(
onNotification: (notification) {
if (_scrollController.position.userScrollDirection == ScrollDirection.reverse) {
_controller.forward();
return true;
}
if (_scrollController.position.userScrollDirection == ScrollDirection.forward) {
_controller.reverse();
return true;
}
return false;
},
child: ListView(
controller: _scrollController,
children: List.generate(
200,
(index) => ListTile(
title: Text(index.toString()),
),
),
),
),
);
}
}
应该是如果用户向下滚动,我希望应用栏高度和底部栏高度动画化(减少) &反之亦然,如果用户 向上滚动 。
您可以复制粘贴运行下面的完整代码
您需要以下
animation.addListener(() {
setState(() {});
});
工作演示
完整代码
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,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: SampleApp(),
);
}
}
class SampleApp extends StatefulWidget {
@override
_SampleAppState createState() => _SampleAppState();
}
class _SampleAppState extends State<SampleApp> with TickerProviderStateMixin {
Animation<double> animation;
AnimationController _controller;
ScrollController _scrollController;
@override
void initState() {
super.initState();
print("$kToolbarHeight");
_controller =
AnimationController(vsync: this, duration: Duration(milliseconds: 240));
animation = Tween(begin: kToolbarHeight, end: 0.0).animate(_controller);
_scrollController = ScrollController();
animation.addListener(() {
setState(() {});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
child: Container(color: Colors.red),
preferredSize: Size.fromHeight(animation.value),
),
bottomNavigationBar:
Container(height: animation.value, color: Colors.red),
floatingActionButton: Container(
width: 50.0,
height: 50.0,
child: Center(
child: FittedBox(
child: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.arrow_upward),
),
),
),
),
body: NotificationListener(
onNotification: (notification) {
if (_scrollController.position.userScrollDirection ==
ScrollDirection.reverse) {
print("reverse");
_controller.forward();
return true;
}
if (_scrollController.position.userScrollDirection ==
ScrollDirection.forward) {
print("forward");
_controller.reverse();
return true;
}
return false;
},
child: ListView(
controller: _scrollController,
children: List.generate(
200,
(index) => ListTile(
title: Text(index.toString()),
),
),
),
),
);
}
}