1. 程式人生 > >Flutter 實現下拉刷新 非安卓原生效果

Flutter 實現下拉刷新 非安卓原生效果

clas The gin off 偏移量 -h nts ddl 坐標

先附上連接

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),
       );
     }
  }

Flutter 實現下拉刷新 非安卓原生效果