代码之家  ›  专栏  ›  技术社区  ›  DolDurma

在滚动列表视图上显示和隐藏容器

  •  0
  • DolDurma  · 技术社区  · 5 年前

    Container 滚动时带有动画 ListView

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

    enter image description here

    示例视频

    https://imgur.com/a/auEzJQk


    编辑:

    每次向下滚动时,我都需要显示 每次我向上滚动,我都想把它藏起来。它不应该依赖于 .

    0 回复  |  直到 5 年前
        1
  •  7
  •   CopsOnRoad    5 年前

    不知道我是否正确地回答了你的问题,这就是你想要达到的目的吗?

    enter image description here


    代码:

    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)),
          ),
        );
      }
    }
    
        2
  •  8
  •   user10539074 user10539074    5 年前
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        const double HEIGHT = 96;
        final ValueNotifier<double> notifier = ValueNotifier(0);
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          home: Scaffold(
            appBar: AppBar(title: const Text('Test')),
            body: Stack(
              children: [
                NotificationListener<ScrollNotification>(
                  onNotification: (n) {
                    if (n.metrics.pixels <= HEIGHT) {
                      notifier.value = n.metrics.pixels;
                    }
                    return false;
                  },
                  child: ListView.builder(
                    itemCount: 42,
                    itemBuilder: (context, index) {
                      return Container(
                        height: 64,
                        padding: const EdgeInsets.all(16),
                        alignment: Alignment.centerLeft,
                        child: Text('Item $index'),
                      );
                    },
                  ),
                ),
                HideableWidget(height: HEIGHT, notifier: notifier),
              ],
            ),
          ),
        );
      }
    }
    
    class HideableWidget extends StatelessWidget {
      final double height;
      final ValueNotifier<double> notifier;
    
      HideableWidget({@required this.height, @required this.notifier});
    
      @override
      Widget build(BuildContext context) {
        return ValueListenableBuilder<double>(
          valueListenable: notifier,
          builder: (context, value, child) {
            return Transform.translate(
              offset: Offset(0, value - height),
              child: Container(
                height: 80,
                color: Colors.red,
              ),
            );
          },
        );
      }
    }
    

    enter image description here

        3
  •  1
  •   Sanjayrajsinh    5 年前

    我找到了你问题的解决方案。这是演示代码

     class _DemoState extends State<WidgetDemo> {
          ScrollController scrollController = new ScrollController();
          bool isVisible = true;
    
          @override
          initState() {
            super.initState();
            scrollController.addListener(() {
              if (scrollController.position.userScrollDirection ==
                  ScrollDirection.reverse) {
                if (isVisible)
                  setState(() {
                    isVisible = false;
                  });
              }
              if (scrollController.position.userScrollDirection ==
                  ScrollDirection.forward) {
                if (!isVisible)
                  setState(() {
                    isVisible = true;
                  });
              }
            });
          }
    
          @override
          Widget build(BuildContext context) {
            return Scaffold(
              body: Stack(
                children: <Widget>[
                  new CustomScrollView(
                    controller: scrollController,
                    shrinkWrap: true,
                    slivers: <Widget>[
                      new SliverPadding(
                        padding: const EdgeInsets.all(20.0),
                        sliver: new SliverList(
                          delegate: new SliverChildListDelegate(
                            <Widget>[
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                              const Text('My temp data'),
                              const Text('Wow its working'),
                            ],
                          ),
                        ),
                      ),
                    ],
                  ),
                  AnimatedContainer(
                      duration: Duration(milliseconds: 400),
                      height: isVisible ? 60.0 : 0.0,
                      child: new Container(
                        color: Colors.green,
                        width: MediaQuery.of(context).size.width,
                        child: Center(child: Text("Container")),
                      )),
                ],
              ),
            );
          }
        }