本文介绍了在滚动ListView时颤动显示和隐藏容器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
在向下滚动 ListView
时,如何显示带有动画的容器
并在向上滚动时将其隐藏。
我要附加的视频并不是我想要的确切实现,而只是给你一个想法。
示例视频
代码:
class HomePage扩展了StatefulWidget {
@override
_HomePageState createState()=> _HomePageState();
}
类_HomePageState扩展了State< HomePage> {
//容器的高度
静态最终值_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;
@override
void initState(){
super.initState();
_controller.addListener(_listener);
}
//整个逻辑都在ListView的此侦听器内
void _listener(){
double offset = _controller.offset;
var direction = _controller.position.userScrollDirection;
if(direction == ScrollDirection.reverse){
_allowForward = true;
if(_allowReverse){
_allowReverse = false;
_prevOffset =偏移量;
_prevForwardOffset = _fromTop;
}
变量差=偏移量-_prevOffset;
_fromTop = _prevForwardOffset +差;
如果(_fromTop> 0)_fromTop = 0;
}否则,如果(direction == ScrollDirection.forward){
_allowReverse = true;
if(_allowForward){
_allowForward = false;
_prevOffset =偏移量;
_prevReverseOffset = _fromTop;
}
变量差=偏移量-_prevOffset;
_fromTop = _prevReverseOffset +差;
if(_fromTop< -_containerHeight)_fromTop = -_containerHeight;
}
setState((){}); //为简单起见,我在这里调用setState,您可以将布尔值仅当_fromTop
}发生真正更改时才调用setState。
@override
Widget build( BuildContext context){
return Scaffold(
appBar:AppBar(title:Text( ListView))),
body:Stack(
children:< Widget> [
_yourListView(),
定位(
上:_fromTop,
左:0,
右:0,
子级:_yourContainer(),
)
],
),
);
}
小部件_yourListView(){
return ListView.builder(
itemCount:100,
controller:_controller,
itemBuilder:( _,index)=> ListTile(title:Text( Item $ index)),
);
}
小部件_yourContainer(){
return Opacity(
opacity:1-(-__ fromTop / _containerHeight),
子级:Container(
高度:_containerHeight,
颜色:Colors.red,
对齐方式:Alignment.center,
子级:Text(您的容器,样式:TextStyle(fontSize:32,fontWeight:FontWeight .bold,颜色: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
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)),
),
);
}
}
这篇关于在滚动ListView时颤动显示和隐藏容器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!