Flutter 在滚动 ListView 上显示和隐藏容器 [英] Flutter show and hide container on scrolling ListView

查看:15
本文介绍了Flutter 在滚动 ListView 上显示和隐藏容器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在向下滚动 ListView 时显示带有动画的 Container 并在向上滚动时隐藏它.

我附上的视频不是我想要的确切实现,但它只是给你一个想法.

示例视频

<小时>

代码:

class HomePage 扩展 StatefulWidget {@覆盖_HomePageState createState() =>_HomePageState();}class _HomePageState 扩展了 State{//容器的高度静态最终_containerHeight = 100.0;//您不需要更改任何这些变量var _fromTop = -_containerHeight;var _controller = ScrollController();var _allowReverse = true,_allowForward = true;var _prevOffset = 0.0;var _prevForwardOffset = -_containerHeight;var _prevReverseOffset = 0.0;@覆盖无效初始化状态(){super.initState();_controller.addListener(_listener);}//整个逻辑都在 ListView 的这个监听器中无效 _listener() {双偏移 = _controller.offset;var 方向 = _controller.position.userScrollDirection;if (direction == ScrollDirection.reverse) {_allowForward = true;如果(_allowReverse){_allowReverse = 假;_prevOffset = 偏移量;_prevForwardOffset = _fromTop;}var差异=偏移量-_prevOffset;_fromTop = _prevForwardOffset + 差值;if (_fromTop > 0) _fromTop = 0;} else if (direction == ScrollDirection.forward) {_allowReverse = true;如果(_allowForward){_allowForward = 假;_prevOffset = 偏移量;_prevReverseOffset = _fromTop;}var差异=偏移量-_prevOffset;_fromTop = _prevReverseOffset + 差值;if (_fromTop < -_containerHeight) _fromTop = -_containerHeight;}setState(() {});//为简单起见,我在这里调用 setState,您可以将布尔值设置为仅在 _fromTop 发生真正变化时调用 setState}@覆盖小部件构建(BuildContext 上下文){返回脚手架(appBar:AppBar(标题:文本(ListView")),正文:堆栈(孩子们:<小部件>[_yourListView(),定位(顶部:_fromTop,左:0,对:0,孩子:_yourContainer(),)],),);}小部件 _yourListView() {返回 ListView.builder(项目数:100,控制器:_控制器,itemBuilder: (_, index) =>ListTile(title: Text("Item $index")),);}小部件 _yourContainer() {返回不透明度(不透明度:1 - (-_fromTop/_containerHeight),孩子:容器(高度:_containerHeight,颜色:颜色.红色,对齐:对齐中心,child: Text("Your Container", style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold, color: Colors.white)),),);}}

How can I show a Container with animation on scrolling ListView down and hide it when scrolling up.

The video I am attaching is not exact implementation I want but it is just to give you an idea.

Sample video

https://imgur.com/a/auEzJQk


Edit:

Every time I scroll down, I need to show the Container and every time I scroll up, I want to hide it. It shouldn't depend on the index of the ListView.

解决方案

Not sure if I got your question properly, is this what you are trying to achieve?

Screenshot:


Code:

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  // Height of your Container
  static final _containerHeight = 100.0;

  // You don't need to change any of these variables
  var _fromTop = -_containerHeight;
  var _controller = ScrollController();
  var _allowReverse = true, _allowForward = true;
  var _prevOffset = 0.0;
  var _prevForwardOffset = -_containerHeight;
  var _prevReverseOffset = 0.0;

  @override
  void initState() {
    super.initState();
    _controller.addListener(_listener);
  }

  // entire logic is inside this listener for ListView
  void _listener() {
    double offset = _controller.offset;
    var direction = _controller.position.userScrollDirection;

    if (direction == ScrollDirection.reverse) {
      _allowForward = true;
      if (_allowReverse) {
        _allowReverse = false;
        _prevOffset = offset;
        _prevForwardOffset = _fromTop;
      }

      var difference = offset - _prevOffset;
      _fromTop = _prevForwardOffset + difference;
      if (_fromTop > 0) _fromTop = 0;
    } else if (direction == ScrollDirection.forward) {
      _allowReverse = true;
      if (_allowForward) {
        _allowForward = false;
        _prevOffset = offset;
        _prevReverseOffset = _fromTop;
      }

      var difference = offset - _prevOffset;
      _fromTop = _prevReverseOffset + difference;
      if (_fromTop < -_containerHeight) _fromTop = -_containerHeight;
    }
    setState(() {}); // for simplicity I'm calling setState here, you can put bool values to only call setState when there is a genuine change in _fromTop
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("ListView")),
      body: Stack(
        children: <Widget>[
          _yourListView(),
          Positioned(
            top: _fromTop,
            left: 0,
            right: 0,
            child: _yourContainer(),
          )
        ],
      ),
    );
  }

  Widget _yourListView() {
    return ListView.builder(
      itemCount: 100,
      controller: _controller,
      itemBuilder: (_, index) => ListTile(title: Text("Item $index")),
    );
  }

  Widget _yourContainer() {
    return Opacity(
      opacity: 1 - (-_fromTop / _containerHeight),
      child: Container(
        height: _containerHeight,
        color: Colors.red,
        alignment: Alignment.center,
        child: Text("Your Container", style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold, color: Colors.white)),
      ),
    );
  }
}

这篇关于Flutter 在滚动 ListView 上显示和隐藏容器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆