在 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()),
            ),
          ),
        ),
      ),
    );
  }
}