Skip to content

Commit

Permalink
Merge pull request #639 from percival888/v3
Browse files Browse the repository at this point in the history
fix: fixed a bug with refresh for mutiple times
  • Loading branch information
xuelongqy authored Nov 16, 2022
2 parents bd4e4fe + b0aad09 commit 5d6c4d4
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 3 deletions.
3 changes: 3 additions & 0 deletions example/lib/config/routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:example/page/sample/chat_page.dart';
import 'package:example/page/sample/listener_header_page.dart';
import 'package:example/page/sample/nested_scroll_view.dart';
import 'package:example/page/sample/page_view_page.dart';
import 'package:example/page/sample/refresh_multiple_times_page.dart';
import 'package:example/page/sample/refresh_on_start_page.dart';
import 'package:example/page/sample/sample_page.dart';
import 'package:example/page/sample/secondary_page.dart';
Expand Down Expand Up @@ -36,6 +37,7 @@ class Routes {
static const nestedScrollViewSample = '/sample/nested-scroll-view';
static const carouselSample = '/sample/carousel';
static const refreshOnStartSample = '/sample/refresh-on-start';
static const refreshMutipleTimes = '/sample/refresh-mutiple-times';
static const listenerSample = '/sample/listener';
static const secondarySample = '/sample/secondary';
static const chatSample = '/sample/chat';
Expand Down Expand Up @@ -70,6 +72,7 @@ class Routes {
name: nestedScrollViewSample, page: () => const NestedScrollViewPage()),
GetPage(name: carouselSample, page: () => const CarouselPage()),
GetPage(name: refreshOnStartSample, page: () => const RefreshOnStartPage()),
GetPage(name: refreshMutipleTimes, page: () => const RefreshMutipleTimesPage()),
GetPage(name: listenerSample, page: () => const ListenerHeaderPage()),
GetPage(name: secondarySample, page: () => const SecondaryPage()),
GetPage(name: chatSample, page: () => const ChatPage()),
Expand Down
211 changes: 211 additions & 0 deletions example/lib/page/sample/refresh_multiple_times_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
import 'package:example/widget/skeleton_item.dart';
import 'package:flutter/material.dart';
import 'package:easy_refresh/easy_refresh.dart';
import 'package:get/get.dart';

class RefreshMutipleTimesPage extends StatefulWidget {
const RefreshMutipleTimesPage({Key? key}) : super(key: key);

@override
State<RefreshMutipleTimesPage> createState() =>
_RefreshMutipleTimesPageState();
}

class _RefreshMutipleTimesPageState extends State<RefreshMutipleTimesPage> {
late EasyRefreshController _controller;
int _count = 10;
final Axis _scrollDirection = Axis.vertical;
final _CIProperties _headerProperties = _CIProperties(
name: 'Header',
alignment: MainAxisAlignment.center,
infinite: false,
);
final _CIProperties _footerProperties = _CIProperties(
name: 'Footer',
alignment: MainAxisAlignment.start,
infinite: true,
);
var _selectFilterConditions = <String>[];

@override
void initState() {
super.initState();
_controller = EasyRefreshController(
controlFinishRefresh: true,
controlFinishLoad: true,
);
}

@override
void dispose() {
_controller.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
final propertiesItems = [_headerProperties, _footerProperties];
return Scaffold(
appBar: AppBar(
title: Text('Classic'.tr),
bottom: PreferredSize(
preferredSize: const Size.fromHeight(50),
child: Container(
height: 50,
color: Colors.black12,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: _conditionButtons(),
)),
),
),
body: EasyRefresh(
clipBehavior: Clip.none,
controller: _controller,
header: ClassicHeader(
clamping: _headerProperties.clamping,
backgroundColor: _headerProperties.background
? Theme.of(context).colorScheme.surfaceVariant
: null,
mainAxisAlignment: _headerProperties.alignment,
showMessage: _headerProperties.message,
showText: _headerProperties.text,
infiniteOffset: _headerProperties.infinite ? 70 : null,
triggerWhenReach: _headerProperties.immediately,
dragText: 'Pull to refresh'.tr,
armedText: 'Release ready'.tr,
readyText: 'Refreshing...'.tr,
processingText: 'Refreshing...'.tr,
processedText: 'Succeeded'.tr,
noMoreText: 'No more'.tr,
failedText: 'Failed'.tr,
messageText: 'Last updated at %T'.tr,
),
footer: ClassicFooter(
clamping: _footerProperties.clamping,
backgroundColor: _footerProperties.background
? Theme.of(context).colorScheme.surfaceVariant
: null,
mainAxisAlignment: _footerProperties.alignment,
showMessage: _footerProperties.message,
showText: _footerProperties.text,
infiniteOffset: _footerProperties.infinite ? 70 : null,
triggerWhenReach: _footerProperties.immediately,
dragText: 'Pull to load'.tr,
armedText: 'Release ready'.tr,
readyText: 'Loading...'.tr,
processingText: 'Loading...'.tr,
processedText: 'Succeeded'.tr,
noMoreText: 'No more'.tr,
failedText: 'Failed'.tr,
messageText: 'Last updated at %T'.tr,
),
onRefresh: _headerProperties.disable
? null
: () async {
_refreshData();
},
onLoad: _footerProperties.disable
? null
: () async {
await Future.delayed(const Duration(seconds: 2));
if (!mounted) {
return;
}
setState(() {
_count += 5;
});
_controller.finishLoad(_count >= 20
? IndicatorResult.noMore
: IndicatorResult.success);
},
child: ListView.builder(
clipBehavior: Clip.none,
scrollDirection: _scrollDirection,
padding: EdgeInsets.zero,
itemCount: _count,
itemBuilder: (ctx, index) {
return SkeletonItem(
direction: _scrollDirection,
);
},
),
),
);
}

/// refresh data
void _refreshData() async {
await Future.delayed(const Duration(seconds: 2));
if (!mounted) {
return;
}
setState(() {
_count = 10;
});
_controller.finishRefresh();
_controller.resetFooter();
}

/// filter condition list
List<Widget> _conditionButtons() {
List<String> titles = ["筛选条件1", "筛选条件2", "筛选条件3", "筛选条件4"];
return titles
.map(
(e) => Container(
padding: EdgeInsets.symmetric(horizontal: 3),
child: TextButton(
child: Text(e),
style: ButtonStyle(
minimumSize: MaterialStateProperty.resolveWith(
(states) {
return const Size(50, 30);
},
),
shape: MaterialStateProperty.resolveWith((states) {
return RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
);
}),
backgroundColor: MaterialStateProperty.resolveWith(
(states) {
return _selectFilterConditions.contains(e) ? Colors.orange : Colors.white;
},
),
),
onPressed: () {
setState(() {
if (_selectFilterConditions.contains(e)) {
_selectFilterConditions.remove(e);
} else {
_selectFilterConditions.add(e);
}
_controller.callRefresh();
_refreshData();
});
},
),
),
)
.toList();
}
}

/// Classic indicator properties.
class _CIProperties {
final String name;
bool disable = false;
bool clamping = false;
bool background = false;
MainAxisAlignment alignment;
bool message = true;
bool text = true;
bool infinite;
bool immediately = false;

_CIProperties({
required this.name,
required this.alignment,
required this.infinite,
});
}
8 changes: 8 additions & 0 deletions example/lib/page/sample/sample_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ class _SamplePageState extends State<SamplePage> {
icon: Icons.refresh,
onTap: () => Get.toNamed(Routes.refreshOnStartSample),
),
ListItem(
title: 'Refresh mutiple times'.tr,
subtitle:
'Modify the filter conditions during the refresh process and refresh again'
.tr,
icon: Icons.refresh,
onTap: () => Get.toNamed(Routes.refreshMutipleTimes),
),
ListItem(
title: 'Listener'.tr,
subtitle: 'Use listener to respond anywhere'.tr,
Expand Down
4 changes: 2 additions & 2 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ dependencies:
url_launcher: ^6.1.5
flutter_spinkit: ^5.1.0
flare_flutter: ^3.0.2
extended_nested_scroll_view:
path: ../../extended_nested_scroll_view
extended_nested_scroll_view: 5.1.3
# path: ../../extended_nested_scroll_view
get: ^4.6.5
convert: ^3.0.2
carousel_slider: ^4.1.1
Expand Down
8 changes: 7 additions & 1 deletion lib/src/notifier/indicator_notifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,7 @@ abstract class IndicatorNotifier extends ChangeNotifier {
/// Finish task and return the result.
/// [result] Result of task completion.
void _finishTask([IndicatorResult result = IndicatorResult.success]) {
if (!_waitTaskResult) {
if (!_waitTaskResult && _result != result && _mode != IndicatorMode.inactive) {
_result = result;
_setMode(IndicatorMode.processed);
_processing = false;
Expand Down Expand Up @@ -724,6 +724,9 @@ abstract class IndicatorNotifier extends ChangeNotifier {
if (processedDuration == Duration.zero) {
_ambiguate(WidgetsBinding.instance)!.addPostFrameCallback((timeStamp) {
_mode = IndicatorMode.done;
if (offset == 0) {
_mode = IndicatorMode.inactive;
}
// Trigger [Scrollable] rollback
if (oldMode == IndicatorMode.processing &&
!userOffsetNotifier.value) {
Expand All @@ -733,6 +736,9 @@ abstract class IndicatorNotifier extends ChangeNotifier {
} else {
Future.delayed(processedDuration, () {
_setMode(IndicatorMode.done);
if (offset == 0) {
_mode = IndicatorMode.inactive;
}
// Trigger [Scrollable] rollback
if (!userOffsetNotifier.value) {
_resetBallistic();
Expand Down

0 comments on commit 5d6c4d4

Please sign in to comment.