flutter 中監聽滑動事件

tabbin發表於2019-06-26

Flutter 監聽滑動螢幕

在移動端,各個平臺或UI系統的原始指標事件模型基本都是一致,即:一次完整的事件分為三個階段:手指按下、手指移動、和手指抬起,而更高階別的手勢(如點選、雙擊、拖動等)都是基於這些原始事件的。

Flutter中可以使用Listener widget來監聽原始觸控事件,它也是一個功能性widget。

Listener的常見屬性

屬性 型別 說明
onPointerDown (PointerDownEvent event){} 手指按下時觸發
onPointerMove (PointerDownEvent event){} 手指在螢幕滑動時觸發
onPointerUp (PointerDownEvent event){} 手指離開螢幕時觸發
onPointerCancel (PointerDownEvent event){} 取消觸控時觸發
Listener({
  Key key,
  this.onPointerDown, //手指按下回撥
  this.onPointerMove, //手指移動回撥
  this.onPointerUp,//手指抬起回撥
  this.onPointerCancel,//觸控事件取消回撥
  this.behavior = HitTestBehavior.deferToChild, //在命中測試期間如何表現
  Widget child
})

用法如下:

Listener(
  onPointerDown: (dowPointEvent){},
  onPointerMove: (movePointEvent){},
  onPointerUp: (upPointEvent){},
  child: Container(
     child: Text('Listener的監聽')
  )
);

使用場景一: 下拉重新整理,上拉載入

如果實現下拉重新整理,必須藉助RefreshIndicator,在listview外面包裹一層RefreshIndicator,然後在RefreshIndicator裡面實現onRefresh方法。監聽的方法有很多種,就不一一闡述了,這裡主要說一下經常使用的兩種方法。

  /// 下拉重新整理,這裡必須使用async,不然會報錯
  Future<Null> _refresh() async {
    final Completer<Null> completer = new Completer<Null>();
    _dataList.clear(); // 清空資料
    setState(() {
      page = 1;
    });
    loadData(completer); // 載入資料
    return completer.future;
  }

載入更多需要對ListView進行監聽,所以需要進行監聽器的設定,在State中進行監聽器的初始化。

ScrollController _scrollController = new ScrollController(); // 初始化滾動監聽器,載入更多使用

1、直接監聽_scrollController,根據是否滑動到底部來判斷是否需要載入更多

_scrollController.addListener(() {
      // 如果滑動到底部
      if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
            // do something
      }
 });
RefreshIndicator(
    onRefresh: _refresh, // 下拉重新整理
    child: ListView.builder(
        padding: EdgeInsets.only(bottom: Adapt.px(40)),
        shrinkWrap: true,
        controller: _scrollController,
        physics: AlwaysScrollableScrollPhysics(),
        itemCount: _dataList.length,
        itemBuilder: (context, item) {
              return listCard(_dataList[item]);
         }
     )
)

2、使用上述的 Listener來監聽,通過Listener的onPointerMove(手指在螢幕上滑動)來監聽滑動的距離,當滑動到底部時載入更多資料

new Listener(
    onPointerMove: (event) {
       var position = event.position.distance;
       var detal = position - lastDownY;
       if (detal > 0) {
          print("================向下移動================");
        } else {
            // 所摸點長度 +滑動距離  = IistView的長度  說明到達底部
            print("================向上移動================");
            print("scrollController==滑動距離=======${(position - downY)}");
            var scrollExtent = scrollController.position.maxScrollExtent;
            print("scrollController==ListView最大長度===${scrollExtent}");
            print("scrollController==所摸點長度===${scrollController.offset}");
            print("scrollController==所摸點離螢幕距離===${position}");
            var result = scrollController.offset +(position - downY).abs();
            if (result >= scrollExtent) {
                print("scrollController====到達底部");
                 lastListLength = scrollExtent;
                 loadMore(); // 載入更多資料
             }
       }
      lastDownY = position;
     },
     child: new ListView.builder(
        controller: scrollController,
        itemCount: datas == null ? 0 : datas.length,
        itemBuilder: (BuildContext context, int index) {
               return Container(child: Text('列表${index}') )
        }
     )
 );

使用場景二 , 滑動螢幕時,隱藏掉鍵盤

日常使用TextField時候,彈出來的鍵盤如果是按鈕提交有時候會出現鍵盤不自動隱藏關閉的情況,可以觸發關閉彈出來的鍵盤。

FocusScope.of(context).requestFocus(FocusNode());
// 或者
FocusNode _foucusNode = new FocusNode();
_foucusNode.unfocus();

使用 Listener監聽,在滑動螢幕的時候關閉鍵盤

Listener(
    onPointerMove: (movePointEvent){
        _foucusNode.unfocus();
    },
   child: return SingleChildScrollView(
        controller: _scrollController,
        child: Column(
          children: <Widget>[
            // some widget
          ],
        )
    )
)
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章