丈夫志四海,万里犹比邻。这篇文章主要讲述Flutter 实现下拉刷新非安卓原生效果相关的知识,希望能为你提供帮助。
先附上连接
https://github.com/dikeboy/flutter-refrensh
这里涉及到flutter中的 几块
动画 ,事件点击, 异步,
要自定义下拉刷新
首先必须要了解Flutter 中的事件监听方法
https://flutter.io/docs/development/ui/advanced/gestures
flutter 的手势主要是两个类listener 和GestureDecetor
Listener 主要类似touchevent
包括 按下,移动,松开 取消(划出屏幕)
GestureDecetor 主要就是一些手势形成效果
点击 双击 长按之类的
我这里是写在基类里,因为调用到修改界面
当然你也可以改成Mixin
因为我这里是对ListView进行处理
也就是通过修改ListView的第一个header高度来实现下拉效果
getRow(int position){ if(position==0){ return getRfrenshHeader(); } else{ returnText(list[position-1]); } }
这里 -1 是因为本身header的高度已经算一个Item了
首先看下 state 的 initState方法
@override initState(){ super.initState(); animationController = AnimationController( duration: const Duration(milliseconds: 300), vsync: this); //定义了一个300毫秒的动画控制器 animation = Tween(begin: 1.0, end: 0.0).animate(animationController); //beginend 也就是300毫秒时间内aimation的值从1.0 到0.0变化 animation.addListener(() { setState(() { // the animation object’s value is the changed state headHeight = (len-headNormalHeight) *animation.value+headNormalHeight; //从touchUp 释放开始header偏移量从1.0 到0.0移动最终剩下header的高度 }); }); }
Listener的实例化
typedef MStartRefrensh = void Function(); //定义一个方法用户回调类似接口回调吧 getPullListener({Widget child, MStartRefrensh startRefrensh,double height}){ this.pointerUpListener = startRefrensh; headNormalHeight=height; //初始化Header的高度 if(scrollController==null){ scrollController = ScrollController(initialScrollOffset: height); //初始化滚动条flutter中如果需要监听 列表滑动都需要滚动条 } Listener listener = new Listener( child: child, onPointerDown: pointDown,onPointerUp: pointUp,onPointerMove: pointMove,onPointerCancel: pointCancle,); //这里也就是我们4个手势的监听方法 if(!firstJump){ setState(() { if(!firstJump& & scrollController.hasClients){//hasClients可以用来判断 scrollerController是否已经绑定到listview上 firstJump =true; scrollController.jumpTo(headNormalHeight); //第一次加载的时候 我们直接跳到Header的高度从而让header隐藏在屏幕上面 } }); } return listener; }
下面看下手势事件
pointDown(PointerDownEvent event){//没没啥特别 记录下touchdown的坐标 dx = event.position.dx; dy=event.position.dy; isTouchDown = true; } pointUp(PointerUpEvent event){//释放的时候 如果head大于我们初始化的head 就说明需要刷新启动一个回滚动画
if(headHeight> headNormalHeight){ startUpAnimation(headHeight); } else{ setState((){ headHeight=headNormalHeight; //这里主要是重置避免未知问题 }); }isTouchDown = false; }pointCancle(PointerCancelEvent event){ //cancel跟UP逻辑一样也可以自定义 if(headHeight> headNormalHeight){ startUpAnimation(headHeight); } else{ setState((){ headHeight=headNormalHeight; }); } isTouchDown = false; } pointMove(PointerMoveEvent event){//print(_scrollController.position.pixels); setState(() { if(event.position.dy- dy> 0) headHeight = (event.position.dy- dy)/2+headNormalHeight; //这里我设置header高度是滑动距离的1/2实际效果有些也会有越滑越慢 可以根据开根号 或者2次方实现 }); }
下面是动画
startUpAnimation(double len) { this.len = len; if (animationController.isCompleted) { animationController.reset(); //动画结束后重置以便下次接着用 } animationController.forward().then((_) { headHeight = headNormalHeight; pointerUpListener(); //这个是自定义的回调事件 也就是初始化的时候传入的 // }); }
刷新的header
//这里就用了系统的滚动条要重写下来动画啥的都可以修改这里
getRfrenshHeader(){
if(headHeight==headNormalHeight& & !isTouchDown){
return Container(
child:SizedBox(
child: CircularProgressIndicator(valueColor: new AlwaysStoppedAnimation< Color> (Colors.orange)),
height: 20.0,
width: 20.0,
),
alignment: Alignment.center,
height:headHeight,
);
}
else{
return Container(
child:SizedBox(
child: Row(children: < Widget> [
new Image.asset(‘images/drop_refrensh.png‘),
Text("释放刷新")
],
mainAxisAlignment: MainAxisAlignment.center,),
height: 20.0,
),
alignment: Alignment.center,
height:headHeight,
);
}
}
刷新结束需要主动关闭
finishLoading(){ if(scrollController!=null& & scrollController.hasClients){ scrollController.animateTo( headNormalHeight, curve: Curves.easeOut, duration: const Duration(milliseconds: 100), ); } }
【Flutter 实现下拉刷新非安卓原生效果】
推荐阅读
- Android 底部导航栏的xml
- 022_applescript教程
- Flask app.config 的配置
- android studio相关配置
- Android课程设计 人脸识别签到
- PyQt5中sys.argv和sys.exit(app.exec_())
- Android-系统绘图真相
- C# Dapper 基本使用 增删改查事务等
- Vant Weapp的dialog组件在mpvue小程序中使用注意事项