【问题标题】:How to detect the last direction user scrolled如何检测用户滚动的最后方向
【发布时间】:2020-08-04 18:54:13
【问题描述】:

我有下面的代码,可以在用户向下或向上滚动时更改工厂的不透明度。但为此,我多次调用setState() 方法。有什么方法可以检测用户滚动的最后一个方向,以便我当时只能Once调用setState()?或者,如果您可以为此定义一个新的增强功能,我将不胜感激。

@override
void initState() {
super.initState();
_controller = ScrollController()
  ..addListener(() {
    upDirection = _controller.position.userScrollDirection == ScrollDirection.forward;
    upDirection = _controller.position.userScrollDirection == ScrollDirection.reverse;


      if (upDirection)
        setState(() {
          _scrolled = 0.5;
          flag = false;
        });
      else if (!upDirection) {
        setState(() {
          _scrolled = 1.0;
        });
        flag = false;
      }

  });
}

这是列表

    return Scaffold(
    body:
    SingleChildScrollView(
      controller: _controller,
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(),
            Container(),
            Container(),
            Container(),
            Container(),
            Container(),
          ],
        ),
      ),
    ),

  floatingActionButton: AnimatedOpacity(
    opacity: _scrolled,
    duration: Duration(milliseconds: 100),
    child: FloatingActionButton(
      onPressed: (){},
      child: Icon(Icons.settings),
          ),
        ),
  floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
);

【问题讨论】:

    标签: flutter flutter-layout flutter-animation


    【解决方案1】:

    问题是每次控制器上有新事件时都会调用您添加的侦听器。这就是为什么您的setState 被反复调用的原因。

    您可以使用标志来防止重复调用setState

    工作代码

    void initState() {
        ScrollDirection _lastScrollDirection; // <---- Notice the new variable here.
        _controller = ScrollController();
    
        _controller.addListener(() {
          if (_lastScrollDirection != _controller.position.userScrollDirection) {
            _lastScrollDirection = _controller.position.userScrollDirection;
    
            setState(() {
              //You can set whatever you want here. 
              //It will only get called once when user changes direction.
            });
    
            print('Scroll direction changed --> $_lastScrollDirection');
          }
        });
        super.initState();
      }
    
    

    演示:

    【讨论】:

      【解决方案2】:

      感谢 Omer Celik,完整代码如下所示,您可以对其进行自定义:

      import 'package:flutter/material.dart';
      import 'package:flutter/rendering.dart';
      
      void main() => runApp(MaterialApp());
      
      class MyApp extends StatelessWidget {
      
        @override
        Widget build(BuildContext context) {
          return MaterialApp(
            home: MainPage(),
          );
        }
      }
      
      class MainPage extends StatefulWidget {
      
        @override
        _MainPageState createState() => _MainPageState();
      }
      
      class _MainPageState extends State<MainPage> {
      
        ScrollController _controller;
        double _scrolled = 1.0;
      
      
        @override
        void initState() {
          ScrollDirection _lastScrollDirection;
          _controller = ScrollController();
      
          _controller.addListener(() {
            if (_lastScrollDirection != _controller.position.userScrollDirection) {
              _lastScrollDirection = _controller.position.userScrollDirection;
      
      
                if (_lastScrollDirection == ScrollDirection.forward) {
                  setState(() {
                  _scrolled = 1.0;
                  });
                }
                else if (_lastScrollDirection == ScrollDirection.reverse) {
                  setState(() {
                    _scrolled = 0.5;
                  });
                }
            }
          });
          super.initState();
        }
      
        @override
        Widget build(BuildContext context) {
      
          return Scaffold(
              body:
      
              ListView.builder(
                controller: _controller,
                physics: BouncingScrollPhysics(),
                padding: const EdgeInsets.all(16.0),
                itemCount: 50,
                itemBuilder: _buildItem,
              ),
      
      
            floatingActionButton: AnimatedOpacity(
              opacity: _scrolled,
              duration: Duration(milliseconds: 700),
              child: FloatingActionButton(
                onPressed: (){},
                child: Icon(Icons.settings),
              ),
            ),
            floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
          );
        }
        Widget _buildItem(BuildContext context, int index) {
          return Container(
            child: Text(index.toString()),
          );
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-11-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-08
        • 2014-08-20
        • 2014-09-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多