如何处理ListView滚动方向

问题描述 投票:0回答:3

我有一个虚拟的物品清单 我想在向上滑动方向显示一个浮动操作按钮并在向下方向隐藏它。 我怎样才能实现这个功能?

class _MyHomePageState extends State<MyHomePage> {
  bool upDirection = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: Container(
          child: Row(
            children: <Widget>[
              Expanded(
                  child: ListView.builder(
                    itemCount: 100,
                    itemBuilder: (context,index){
                      return ListTile(
                        title: Text(index.toString()),
                      );
                    },
                  ),
              )
            ],
          ),
        ),
      ),
      floatingActionButton:upDirection==true?FloatingActionButton(onPressed: (){},):Container() ,
    );
  }
}
flutter dart flutter-layout
3个回答
30
投票

截图:

您所需要的只是一个

NotificationListener.onNotification
回调:

NotificationListener<UserScrollNotification>(
  onNotification: (notification) {
    final ScrollDirection direction = notification.direction;
    return true;
  },
  child: ListView.builder(
    itemCount: 100,
    itemBuilder: (_, i) => ListTile(title: Text('$i')),
  ),
)

完整代码:

bool _visible = true;
  
@override
Widget build(BuildContext context) {
  return Scaffold(
    floatingActionButton: AnimatedOpacity(
      duration: Duration(milliseconds: 400),
      opacity: _visible ? 1 : 0,
      child: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {},
      ),
    ),
    body: NotificationListener<UserScrollNotification>(
      onNotification: (notification) {
        final ScrollDirection direction = notification.direction;
        setState(() {
          if (direction == ScrollDirection.reverse) {
            _visible = false;
          } else if (direction == ScrollDirection.forward) {
            _visible = true;
          }
        });
        return true;
      },
      child: ListView.builder(
        itemCount: 100,
        itemBuilder: (_, i) => ListTile(title: Text('$i')),
      ),
    ),
  );
}

1
投票

虽然上面的解决方案回答了问题,但我认为它有点低效,因为每次方向发生变化时你都会调用

setState()
。这可能适用于小型应用程序,但在大型复杂应用程序中可能会导致长时间滞后,因为当您调用 s
etState()
时,整个小部件树会重建自身及其后续子项。

我的解决方案?使用ProviderConsumer

Provider acts like a reference to a widget and a certain variable of which you want to keep a track of and using consumer you can listen to change when you need and where you need.

相对于 setState() 的好处,当调用消费者的构建器方法时,它只会重建侦听它的小部件(在您的情况下为底部应用程序栏),并且不会影响小部件树的其余部分。

此外,提供者是 flutter 状态管理的支柱,因此我强烈建议他们尽快了解。


0
投票

使用 ScrollController 我们可以在 listview、singlechildscrollview、girdview 中使用此方法检查上下滚动,当 axis.vertical 和 axis.horizontal 可以检查从左到右滚动时

final ScrollController _scrollController = ScrollController();
@override
void initState() {
_scrollController.addListener(() {
  if (_scrollController.position.userScrollDirection ==
      ScrollDirection.forward) {
    update(0.0, true);
  } else if (_scrollController.position.userScrollDirection ==
      ScrollDirection.reverse) {
    update(70, false);
  }
});
  super.initState();
}
© www.soinside.com 2019 - 2024. All rights reserved.