如何检测用户滚动的最后方向
How to detect the last direction user scrolled
我有下面的代码可以更改用户向下或向上滚动时的晶圆厂不透明度。但是为了它,我多次调用 setState()
方法。有什么方法可以检测用户滚动的最后一个方向,以便我可以在那一刻只调用 setState()
一次 Once?或者,如果您能为此定义一个新的增强功能,我将不胜感激。
@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,
);
问题是每次控制器上有新事件时,您添加的侦听器都会被调用。这就是为什么您的 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();
}
演示:
感谢 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()),
);
}
}
我有下面的代码可以更改用户向下或向上滚动时的晶圆厂不透明度。但是为了它,我多次调用 setState()
方法。有什么方法可以检测用户滚动的最后一个方向,以便我可以在那一刻只调用 setState()
一次 Once?或者,如果您能为此定义一个新的增强功能,我将不胜感激。
@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,
);
问题是每次控制器上有新事件时,您添加的侦听器都会被调用。这就是为什么您的 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();
}
演示:
感谢 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()),
);
}
}