咱們在開發過程當中,碰到列表頁展現數據,此時需用用到數據的刷新,那麼Flutter如何實現這個呢?今天咱們使用一個插件來實現下拉刷新,上拉加載git
pull_to_refresh: ^1.5.6
複製代碼
flutter pub get複製代碼
import 'package:pull_to_refresh/pull_to_refresh.dart';
複製代碼
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))),
],
))
],
),
);
}
}複製代碼
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 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
案例中,咱們在下拉刷新的時候延時1秒鐘模擬異步網絡請求數據,1秒鐘以後經過controller改變header的狀態;在上拉加載的時候模擬1.5秒的異步網絡請求數據,添加了8條數據,1.5秒以後經過controller改變footer的狀態。spring
效果演示(初次使用gif軟件是傲軟GIF,使用的試用版,因此右上角有個水印)api
細心的讀者確定知道,爲何個人下來刷新,上拉加載提示語是英文的,怎麼回事?接下來咱們來處理這個問題bash
flutter_localizations:
sdk: flutter
複製代碼
flutter pub get複製代碼
import 'package:flutter_localizations/flutter_localizations.dart';
複製代碼
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;
},
複製代碼
全局配置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(
........
)
);複製代碼
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(),
),
);
}
}
複製代碼
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