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{
     return  Text(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); //begin  end 也就是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),
       );
     }
  }

原文地址:https://www.cnblogs.com/dikeboy/p/10162420.html

时间: 2024-10-10 09:02:15

Flutter 实现下拉刷新 非安卓原生效果的相关文章

Android的下拉刷新带进度条效果

首先看一下运行效果图,程序的下拉刷新参考了视频,在视频页面也提供了源码下载, http://www.imooc.com/learn/135 本篇主要说在此基础上增加了进度条的快速旋转和递增递减处理,在文章最后也会给出源码,这里主要描述一下所用的一个类 RoundProgressBar package com.cayden.listview; import android.content.Context; import android.content.res.TypedArray; import

Android UI设计之&lt;十&gt;自定义ListView,实现QQ空间阻尼下拉刷新和渐变菜单栏效果

转载请注明出处:http://blog.csdn.net/llew2011/article/details/51559694 好久没有写有关UI的博客了,刚刚翻了一下之前的博客,最近一篇有关UI的博客是在2014年写的:Android UI设计之<七>自定义Dialog,实现各种风格效果的对话框,在那篇博客写完后由于公司封闭开发封网以及其它原因致使博客中断至今,中断这么久很是惭愧,后续我会尽量把该写的都补充出来.近来项目有个需求,要做个和QQ空间类似的菜单栏透明度渐变和下拉刷新带有阻尼回弹的效

自定义控件基础02_下拉刷新_侧拉菜单_自定义属性

自定义控件02 自定义控件 ①,纯粹自定义绘制 ②,在原生的基础上追加功能. 1,下拉刷新功能(继承ListView追加功能)(下拉刷新,加载更多,两个功能) 1.1 下拉刷新 ①创建一个类,继承ListView 创建自定义适配器,设置数据 额外:自定义控件会放到view包下 ②自定义控件的头(即下拉的时候显示的view) 推荐名称initHeaderView();在构造方法中初始化这个头 this.addHeaderView()//添加一个头布局的控件,在listView顶部添加一个头 头部u

Android仿苹果版QQ下拉刷新实现(一) ——打造简单平滑的通用下拉刷新控件

前言: 因为公司人员变动原因,导致了博主四个月没有动安卓,一直在做IOS开发,如今接近年前,终于可以花一定的时间放在安卓上了.好了,废话不多说,今天我们要带来的效果是苹果版本的QQ下拉刷新.首先看一下目标效果以及demo效果:      因为此效果实现的步骤较多,所以今天博主要实现以上效果的第一步——打造一个通用的下拉刷新控件,具体效果如下: GIF图片比较大,还希望读者能耐心等待一下下从效果图中可以看出,我们的下拉刷新的滑动还是很流畅的,可能大多数开发者用的是XListview或者PullTo

使用 CSS overscroll-behavior 控制滚动行为:自定义下拉刷新和溢出效果

CSS 的新属性 overscroll-behavior 允许开发者覆盖默认的浏览器滚动行为,一般用在滚动到顶部或者底部. 背景 滚动边界和滚动链接(boundary & chaining) 在 APP 中经常使用的抽屉导航(drawer)中,我们期望的效果是:滚动到底部时,滚动停止,因为我们到达了"滚动边界". 但是在 Web 页面中滚动并不会停止,而是继续滚动抽屉后面的内容.效果如下: 我们称这种行为叫滚动链接(scroll chaining). 下拉刷新 pull-to-

ListView下拉刷新,上拉自动加载更多

下拉刷新,Android中非常普遍的功能.为了方便便重写的ListView来实现下拉刷新,同时添加了上拉自动加载更多的功能.设计最初是参考开源中国的Android客户端源码.先看示例图.          图1                                                                                                             图2          图3                      

手机端轻应用模拟原生的下拉刷新效果(JavaScript)

方案一:使用iscoll等有下拉功能的框架. 分析:因为项目的结构已经基本完成,再使用框架,会与原来的结构互相影响: 方案二:用JavaScript.Jquery写. 分析:可能没有直接使用框架的效果好,但可以尽量使效果贴近原生. 综合考虑,采用方案二. ///////////////////////////////////////////////////////////////////////////////////////////////// 参考博客:http://www.cnblogs.

安卓自带下拉刷新SwipeRefreshLayout添加上拉刷新功能

在项目里面要用到刷新库,以前都是使用第三方的,不过看到官方出了  SwipeRefreshLayout之后就用SwipeRefreshLayout,但是不知道什么原因官方SwipeRefreshLayout只提供下拉刷新功能,很多时候我们需要上拉刷新功能,所以下载v4源码修改SwipeRefreshLayout,与之相关联的文件有两个分别是SwipeProgressBar,BakedBezierInterpolator把这三个文件拷贝到项目里面,修改一下包名就可以了.如何实现上拉刷新功能,其

自己封装的工具类,使用原生SwipeRefreshLayout+RecycleView实现下拉刷新和加载更多

实现SwipeRefreshLayout+RecycleView实现刷新 在你的xml文件里写上如下代码: <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/SwipeRefreshLayout" android:layout_width="match_parent" android:layout_height="match_parent"> <andr