Flutter——下拉刷新,上拉加載

    咱們在開發過程當中,碰到列表頁展現數據,此時需用用到數據的刷新,那麼Flutter如何實現這個呢?今天咱們使用一個插件來實現下拉刷新,上拉加載git

一:準備工做

1,添加依賴

pull_to_refresh: ^1.5.6
複製代碼

2,獲取依賴

flutter pub get複製代碼

3,在須要使用的文件中導入依賴

import 'package:pull_to_refresh/pull_to_refresh.dart';
複製代碼

二:案例演示

1,建立列表子項組件

class Item extends StatelessWidget {
  Color color;
  IconData icon;
  String mainTitle;
  String subTitle;
  String des;
  int readCount;

  Item(this.color, this.icon, this.mainTitle, this.subTitle, this.des,
      this.readCount);

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.fromLTRB(10.0, 5.0, 10.0, 5.0),
      height: 90.0,
      child: Row(
        children: <Widget>[
          Container(
            width: 90.0,
            color: color,
            alignment: Alignment.center,
            child: Icon(icon, color: Colors.white),
          ),
          SizedBox(width: 10),
          Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Expanded(
                      child: Text(mainTitle,
                          style: TextStyle(
                              fontWeight: FontWeight.bold, fontSize: 18.0))),
                  Expanded(child: Text(subTitle, style: TextStyle(fontSize: 14.0))),
                  Expanded(
                      child: Text(
                        des,
                        style: TextStyle(fontSize: 13.0),
                        overflow: TextOverflow.ellipsis,
                      )),
                  Expanded(
                      child: Text("閱讀量:${readCount.toString()}",
                          style: TextStyle(
                              fontWeight: FontWeight.bold,
                              fontSize: 14.0,
                              color: Colors.redAccent))),
                ],
              ))
        ],
      ),
    );
  }
}複製代碼

2,建立數據模型

class ItemModel{
  Color _color;
  IconData _icon;
  String _mainTitle;
  String _subTitle;
  String _des;
  int _readCount;

  ItemModel(this._color, this._icon, this._mainTitle, this._subTitle, this._des,
      this._readCount);

  int get readCount => _readCount;

  set readCount(int value) {
    _readCount = value;
  }

  String get des => _des;

  set des(String value) {
    _des = value;
  }

  String get subTitle => _subTitle;

  set subTitle(String value) {
    _subTitle = value;
  }

  String get mainTitle => _mainTitle;

  set mainTitle(String value) {
    _mainTitle = value;
  }

  IconData get icon => _icon;

  set icon(IconData value) {
    _icon = value;
  }

  Color get color => _color;

  set color(Color value) {
    _color = value;
  }


}複製代碼

3,建立數據提供類

class ListData{
  static List<Widget> getList(){
    List<Widget> models=[];
    ItemModel model1= ItemModel(Colors.red, Icons.airplanemode_active, "軍事新聞", "俄軍大秀戰略",
        "醞釀已久的俄羅斯「中部-2019」戰略演習於16日正式啓動", 2999);
    ItemModel model2= ItemModel(Colors.red, Icons.airplanemode_active, "軍事新聞", "俄「中部」演習",
        "俄羅斯衛星網報道稱,俄羅斯國防部長紹伊古表示,「中央-2019」戰略演習是", 4588);
    ItemModel model3= ItemModel(Colors.red, Icons.airplanemode_active, "軍事新聞", "中國2.7萬噸塢登艦",
        "據印度新德里電視臺16日報道,印度海軍發現7艘中國軍艦在印度洋", 7777);
    ItemModel model4=  ItemModel(Colors.red, Icons.airplanemode_active, "軍事新聞", "針對中國?",
        "美國空軍着力打造軍用5G網絡,5G+VR,飛行員無需上天就能操控戰機;美軍瀕海", 8888);
    ItemModel model5=  ItemModel(Colors.red, Icons.airplanemode_active, "軍事新聞", "「凱旋」防空導彈系統",
        "俄羅斯衛星通信社報道,俄羅斯北方艦隊(Russian Northern Fleet)新聞處", 9999);
    ItemModel model6=  ItemModel(Colors.red, Icons.airplanemode_active, "軍事新聞", "火箭軍還有騎兵連",
        "迅速對禁區「敵特分子」活動區域進行偵察定位,戰鬥小分隊", 104754);
    ItemModel model7= ItemModel(Colors.red, Icons.airplanemode_active, "軍事新聞", "偵察兵跨越冰川",
        "在海拔5000多米的雪域高原,第77集團軍某合成旅的偵察兵們正在進行野外駐訓", 47545);
    ItemModel model8=  ItemModel(Colors.red, Icons.airplanemode_active, "軍事新聞", "香港被護商船",
        "新京報快訊 據北海艦隊官微消息:「感謝海軍!」「祖國萬歲!」,當地時", 124574);

    models.add(Item(model1.color, model1.icon, model1.mainTitle, model1.subTitle, model1.des, model1.readCount));
    models.add(Item(model2.color, model2.icon, model2.mainTitle, model2.subTitle, model2.des, model2.readCount));
    models.add(Item(model3.color, model3.icon, model3.mainTitle, model3.subTitle, model3.des, model3.readCount));
    models.add(Item(model4.color, model4.icon, model4.mainTitle, model4.subTitle, model4.des, model4.readCount));
    models.add(Item(model5.color, model5.icon, model5.mainTitle, model5.subTitle, model5.des, model5.readCount));
    models.add(Item(model6.color, model6.icon, model6.mainTitle, model6.subTitle, model6.des, model6.readCount));
    models.add(Item(model7.color, model7.icon, model7.mainTitle, model7.subTitle, model7.des, model7.readCount));
    models.add(Item(model8.color, model8.icon, model8.mainTitle, model8.subTitle, model8.des, model8.readCount));
    return models;
  }
}複製代碼

4,建立刷新組件

class Pulltorefresh extends StatefulWidget {
  @override
  _PulltorefreshState createState() => _PulltorefreshState();
}

class _PulltorefreshState extends State<Pulltorefresh> {
  List<Widget> datas=ListData.getList();
  RefreshController _controller=RefreshController(initialRefresh: false);

  void _onRefresh() async{
    await Future.delayed(Duration(milliseconds: 1000));
    _controller.refreshCompleted();
  }

  void _onLoading() async{
    await Future.delayed(Duration(milliseconds: 1500));
    ItemModel model=ItemModel(getRandomColor(), Icons.airplanemode_active, "軍事新聞", "俄軍大秀戰略",
        "醞釀已久的俄羅斯「中部-2019」戰略演習於16日正式啓動", 5000);

    this.datas.add(Item(getRandomColor(), model.icon, model.mainTitle, model.subTitle, model.des, model.readCount));
    this.datas.add(Item(getRandomColor(), model.icon, model.mainTitle, model.subTitle, model.des, model.readCount));
    this.datas.add(Item(getRandomColor(), model.icon, model.mainTitle, model.subTitle, model.des, model.readCount));
    this.datas.add(Item(getRandomColor(), model.icon, model.mainTitle, model.subTitle, model.des, model.readCount));
    this.datas.add(Item(getRandomColor(), model.icon, model.mainTitle, model.subTitle, model.des, model.readCount));
    this.datas.add(Item(getRandomColor(), model.icon, model.mainTitle, model.subTitle, model.des, model.readCount));
    this.datas.add(Item(getRandomColor(), model.icon, model.mainTitle, model.subTitle, model.des, model.readCount));
    this.datas.add(Item(getRandomColor(), model.icon, model.mainTitle, model.subTitle, model.des, model.readCount));
    if(mounted)
      setState(() {

      });
    _controller.loadComplete();
  }

  @override
  Widget build(BuildContext context) {

    Widget _itemBuilder(BuildContext context, int position) {

      return Card(child: this.datas[position]);

    }
    return Scaffold(
        appBar: AppBar(
          title: Text("Pulltorefresh"),
        ),
        body: SmartRefresher(
          enablePullDown: true,
          enablePullUp: true,
          header: WaterDropHeader(),
          footer: ClassicFooter(
              loadStyle: LoadStyle.ShowAlways,
              completeDuration: Duration(microseconds: 50),
          ),
          onRefresh: _onRefresh,
          onLoading: _onLoading,
          controller: _controller,
          child: ListView.builder(itemBuilder: _itemBuilder,itemCount: this.datas.length),


        ),


    );
  }


  Color getRandomColor(){
    List<Color> colors=[Colors.deepOrange,Colors.amber,Colors.cyan,Colors.green,Colors.red,Colors.yellow];
    int randomValue=Random().nextInt(colors.length);
    if(randomValue==colors.length){
      randomValue=colors.length-1;
    }
    return colors[randomValue];

  }

}複製代碼

說明:github

  • 將咱們本身的child外面包裹一層SmartRefresher,這個是必須的
  • 屬性enablePullDown,容許下拉刷新
  • 屬性enablePullUp,容許上拉加載
  • 屬性header,表明下拉刷新頭部樣式
  • 屬性footer,表明上拉加載底部樣式
  • 屬性onRefresh,表明下拉刷新的回調
  • 屬性onLoading,表明上拉加載的回調
  • 屬性controller,刷新控件的控制器,用來處理回調狀態等

案例中,咱們在下拉刷新的時候延時1秒鐘模擬異步網絡請求數據,1秒鐘以後經過controller改變header的狀態;在上拉加載的時候模擬1.5秒的異步網絡請求數據,添加了8條數據,1.5秒以後經過controller改變footer的狀態。spring

效果演示(初次使用gif軟件是傲軟GIF,使用的試用版,因此右上角有個水印)api


三:國際化顯示

細心的讀者確定知道,爲何個人下來刷新,上拉加載提示語是英文的,怎麼回事?接下來咱們來處理這個問題bash

1,添加SDK

flutter_localizations:
  sdk: flutter
複製代碼

2,獲取依賴

flutter pub get複製代碼

3,在main.dart文件中導入依賴

import 'package:flutter_localizations/flutter_localizations.dart';
複製代碼

4,在main.dart的MateriaApp裏面添加以下代碼

localizationsDelegates: [
          // 這行是關鍵
          RefreshLocalizations.delegate,
          GlobalWidgetsLocalizations.delegate,
          GlobalMaterialLocalizations.delegate
        ],
        supportedLocales: [
          const Locale('en'),
          const Locale('zh'),
        ],
        localeResolutionCallback:
            (Locale locale, Iterable<Locale> supportedLocales) {
          //print("change language");
          return locale;
        },
複製代碼

5,從新運行,效果以下



四:全局刷新配置

   全局配置RefreshConfiguration,配置子樹下的全部SmartRefresher表現,通常存放於MaterialApp的根部
網絡

// 全局配置子樹下的SmartRefresher,下面列舉幾個特別重要的屬性
     RefreshConfiguration(
         headerBuilder: () => WaterDropHeader(),        // 配置默認頭部指示器,假如你每一個頁面的頭部指示器都同樣的話,你須要設置這個
         footerBuilder:  () => ClassicFooter(),        // 配置默認底部指示器
         headerTriggerDistance: 80.0,        // 頭部觸發刷新的越界距離
         springDescription:SpringDescription(stiffness: 170, damping: 16, mass: 1.9),         // 自定義回彈動畫,三個屬性值意義請查詢flutter api
         maxOverScrollExtent :100, //頭部最大能夠拖動的範圍,若是發生衝出視圖範圍區域,請設置這個屬性
         maxUnderScrollExtent:0, // 底部最大能夠拖動的範圍
         enableScrollWhenRefreshCompleted: true, //這個屬性不兼容PageView和TabBarView,若是你特別須要TabBarView左右滑動,你須要把它設置爲true
         enableLoadingWhenFailed : true, //在加載失敗的狀態下,用戶仍然能夠經過手勢上拉來觸發加載更多
         hideFooterWhenNotFull: false, // Viewport不滿一屏時,禁用上拉加載更多功能
         enableBallisticLoad: true, // 能夠經過慣性滑動觸發加載更多
        child: MaterialApp(
            ........
        )
    );複製代碼

五:完整代碼示例

1,main.dart

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'pages/Pulltorefresh.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return RefreshConfiguration(
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.red,
        ),
        localizationsDelegates: [
          // 這行是關鍵
          RefreshLocalizations.delegate,
          GlobalWidgetsLocalizations.delegate,
          GlobalMaterialLocalizations.delegate
        ],
        supportedLocales: [
          const Locale('en'),
          const Locale('zh'),
        ],
        localeResolutionCallback:
            (Locale locale, Iterable<Locale> supportedLocales) {
          //print("change language");
          return locale;
        },
        home: Pulltorefresh(),
      ),
    );
  }
}
複製代碼

2,Pulltorefresh.dart

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';

///create time : 2019/9/18/018  8:38
///create by : Administrator
///des:刷新組件

class Pulltorefresh extends StatefulWidget {
  @override
  _PulltorefreshState createState() => _PulltorefreshState();
}

class _PulltorefreshState extends State<Pulltorefresh> {
  List<Widget> datas=ListData.getList();
  RefreshController _controller=RefreshController(initialRefresh: false);

  void _onRefresh() async{
    await Future.delayed(Duration(milliseconds: 1000));
    _controller.refreshCompleted();
  }

  void _onLoading() async{
    await Future.delayed(Duration(milliseconds: 1500));
    ItemModel model=ItemModel(getRandomColor(), Icons.airplanemode_active, "軍事新聞", "俄軍大秀戰略",
        "醞釀已久的俄羅斯「中部-2019」戰略演習於16日正式啓動", 5000);

    this.datas.add(Item(getRandomColor(), model.icon, model.mainTitle, model.subTitle, model.des, model.readCount));
    this.datas.add(Item(getRandomColor(), model.icon, model.mainTitle, model.subTitle, model.des, model.readCount));
    this.datas.add(Item(getRandomColor(), model.icon, model.mainTitle, model.subTitle, model.des, model.readCount));
    this.datas.add(Item(getRandomColor(), model.icon, model.mainTitle, model.subTitle, model.des, model.readCount));
    this.datas.add(Item(getRandomColor(), model.icon, model.mainTitle, model.subTitle, model.des, model.readCount));
    this.datas.add(Item(getRandomColor(), model.icon, model.mainTitle, model.subTitle, model.des, model.readCount));
    this.datas.add(Item(getRandomColor(), model.icon, model.mainTitle, model.subTitle, model.des, model.readCount));
    this.datas.add(Item(getRandomColor(), model.icon, model.mainTitle, model.subTitle, model.des, model.readCount));
    if(mounted)
      setState(() {

      });
    _controller.loadComplete();
  }

  @override
  Widget build(BuildContext context) {

    Widget _itemBuilder(BuildContext context, int position) {

      return Card(child: this.datas[position]);

    }
    return Scaffold(
        appBar: AppBar(
          title: Text("Pulltorefresh"),
        ),
        body: SmartRefresher(
          enablePullDown: true,
          enablePullUp: true,
          header: WaterDropHeader(),
          footer: ClassicFooter(
              loadStyle: LoadStyle.ShowAlways,
              completeDuration: Duration(microseconds: 50),
          ),
          onRefresh: _onRefresh,
          onLoading: _onLoading,
          controller: _controller,
          child: ListView.builder(itemBuilder: _itemBuilder,itemCount: this.datas.length),


        ),


    );
  }


  Color getRandomColor(){
    List<Color> colors=[Colors.deepOrange,Colors.amber,Colors.cyan,Colors.green,Colors.red,Colors.yellow];
    int randomValue=Random().nextInt(colors.length);
    if(randomValue==colors.length){
      randomValue=colors.length-1;
    }
    return colors[randomValue];

  }

}


class ItemModel{
  Color _color;
  IconData _icon;
  String _mainTitle;
  String _subTitle;
  String _des;
  int _readCount;

  ItemModel(this._color, this._icon, this._mainTitle, this._subTitle, this._des,
      this._readCount);

  int get readCount => _readCount;

  set readCount(int value) {
    _readCount = value;
  }

  String get des => _des;

  set des(String value) {
    _des = value;
  }

  String get subTitle => _subTitle;

  set subTitle(String value) {
    _subTitle = value;
  }

  String get mainTitle => _mainTitle;

  set mainTitle(String value) {
    _mainTitle = value;
  }

  IconData get icon => _icon;

  set icon(IconData value) {
    _icon = value;
  }

  Color get color => _color;

  set color(Color value) {
    _color = value;
  }


}
class ListData{
  static List<Widget> getList(){
    List<Widget> models=[];
    ItemModel model1= ItemModel(Colors.red, Icons.airplanemode_active, "軍事新聞", "俄軍大秀戰略",
        "醞釀已久的俄羅斯「中部-2019」戰略演習於16日正式啓動", 2999);
    ItemModel model2= ItemModel(Colors.red, Icons.airplanemode_active, "軍事新聞", "俄「中部」演習",
        "俄羅斯衛星網報道稱,俄羅斯國防部長紹伊古表示,「中央-2019」戰略演習是", 4588);
    ItemModel model3= ItemModel(Colors.red, Icons.airplanemode_active, "軍事新聞", "中國2.7萬噸塢登艦",
        "據印度新德里電視臺16日報道,印度海軍發現7艘中國軍艦在印度洋", 7777);
    ItemModel model4=  ItemModel(Colors.red, Icons.airplanemode_active, "軍事新聞", "針對中國?",
        "美國空軍着力打造軍用5G網絡,5G+VR,飛行員無需上天就能操控戰機;美軍瀕海", 8888);
    ItemModel model5=  ItemModel(Colors.red, Icons.airplanemode_active, "軍事新聞", "「凱旋」防空導彈系統",
        "俄羅斯衛星通信社報道,俄羅斯北方艦隊(Russian Northern Fleet)新聞處", 9999);
    ItemModel model6=  ItemModel(Colors.red, Icons.airplanemode_active, "軍事新聞", "火箭軍還有騎兵連",
        "迅速對禁區「敵特分子」活動區域進行偵察定位,戰鬥小分隊", 104754);
    ItemModel model7= ItemModel(Colors.red, Icons.airplanemode_active, "軍事新聞", "偵察兵跨越冰川",
        "在海拔5000多米的雪域高原,第77集團軍某合成旅的偵察兵們正在進行野外駐訓", 47545);
    ItemModel model8=  ItemModel(Colors.red, Icons.airplanemode_active, "軍事新聞", "香港被護商船",
        "新京報快訊 據北海艦隊官微消息:「感謝海軍!」「祖國萬歲!」,當地時", 124574);

    models.add(Item(model1.color, model1.icon, model1.mainTitle, model1.subTitle, model1.des, model1.readCount));
    models.add(Item(model2.color, model2.icon, model2.mainTitle, model2.subTitle, model2.des, model2.readCount));
    models.add(Item(model3.color, model3.icon, model3.mainTitle, model3.subTitle, model3.des, model3.readCount));
    models.add(Item(model4.color, model4.icon, model4.mainTitle, model4.subTitle, model4.des, model4.readCount));
    models.add(Item(model5.color, model5.icon, model5.mainTitle, model5.subTitle, model5.des, model5.readCount));
    models.add(Item(model6.color, model6.icon, model6.mainTitle, model6.subTitle, model6.des, model6.readCount));
    models.add(Item(model7.color, model7.icon, model7.mainTitle, model7.subTitle, model7.des, model7.readCount));
    models.add(Item(model8.color, model8.icon, model8.mainTitle, model8.subTitle, model8.des, model8.readCount));
    return models;
  }
}

class Item extends StatelessWidget {
  Color color;
  IconData icon;
  String mainTitle;
  String subTitle;
  String des;
  int readCount;

  Item(this.color, this.icon, this.mainTitle, this.subTitle, this.des,
      this.readCount);

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.fromLTRB(10.0, 5.0, 10.0, 5.0),
      height: 90.0,
      child: Row(
        children: <Widget>[
          Container(
            width: 90.0,
            color: color,
            alignment: Alignment.center,
            child: Icon(icon, color: Colors.white),
          ),
          SizedBox(width: 10),
          Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Expanded(
                      child: Text(mainTitle,
                          style: TextStyle(
                              fontWeight: FontWeight.bold, fontSize: 18.0))),
                  Expanded(child: Text(subTitle, style: TextStyle(fontSize: 14.0))),
                  Expanded(
                      child: Text(
                        des,
                        style: TextStyle(fontSize: 13.0),
                        overflow: TextOverflow.ellipsis,
                      )),
                  Expanded(
                      child: Text("閱讀量:${readCount.toString()}",
                          style: TextStyle(
                              fontWeight: FontWeight.bold,
                              fontSize: 14.0,
                              color: Colors.redAccent))),
                ],
              ))
        ],
      ),
    );
  }
}
複製代碼


六:結束語

若是示例有誤,煩請指正,不勝感激!app

插件地址:github.com/peng8350/fl…less

相關文章
相關標籤/搜索