Skip to content

Commit 1478c2c

Browse files
committed
feat: NestedScrollView related optimization.
1 parent 85af22f commit 1478c2c

14 files changed

+167
-136
lines changed

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## Next
1+
## V 3.0.3
22
> fix: processedDuration == Duration.zero, can't rebound [#572](https://github.com/xuelongqy/flutter_easy_refresh/pull/572).
33
> fix: [clamping] may not have rebound animation.
44
> fix: Indicator overflow [#575](https://github.com/xuelongqy/flutter_easy_refresh/pull/575).

example/lib/l10n/translations/en.dart

+1
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,5 @@ const en = {
8787
'Dogecoin donation': 'Dogecoin donation',
8888
'%s copied!': '%s copied!',
8989
'Trigger immediately': 'Trigger immediately',
90+
'TabBarView example': 'NestedScrollView + TabBarView example',
9091
};

example/lib/l10n/translations/zh_cn.dart

+1
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,5 @@ const zhCN = {
8585
'Dogecoin donation': '狗狗币捐赠',
8686
'%s copied!': '%s 已复制!',
8787
'Trigger immediately': '立即触发',
88+
'TabBarView example': 'NestedScrollView + TabBarView示例',
8889
};

example/lib/page/sample/nested_scroll_view.dart

+15-23
Original file line numberDiff line numberDiff line change
@@ -61,31 +61,23 @@ class NestedScrollViewPageState extends State<NestedScrollViewPage>
6161
},
6262
body: Column(
6363
children: <Widget>[
64-
PreferredSize(
65-
child: Padding(
66-
padding: const EdgeInsets.symmetric(
67-
horizontal: 8,
64+
TabBar(
65+
controller: _tabController,
66+
labelColor: themeData.colorScheme.primary,
67+
indicatorColor: themeData.colorScheme.primary,
68+
onTap: (index) {
69+
setState(() {
70+
_tabIndex = index;
71+
});
72+
},
73+
tabs: const <Widget>[
74+
Tab(
75+
text: 'List',
6876
),
69-
child: TabBar(
70-
controller: _tabController,
71-
labelColor: themeData.colorScheme.primary,
72-
indicatorColor: themeData.colorScheme.primary,
73-
onTap: (index) {
74-
setState(() {
75-
_tabIndex = index;
76-
});
77-
},
78-
tabs: const <Widget>[
79-
Tab(
80-
text: 'List',
81-
),
82-
Tab(
83-
text: 'Grid',
84-
),
85-
],
77+
Tab(
78+
text: 'Grid',
8679
),
87-
),
88-
preferredSize: const Size(double.infinity, 46.0),
80+
],
8981
),
9082
Expanded(
9183
child: IndexedStack(

example/lib/page/sample/sample_page.dart

+3-3
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ class _SamplePageState extends State<SamplePage> {
4545
onTap: () => Get.toNamed(Routes.nestedScrollViewSample),
4646
),
4747
ListItem(
48-
title: 'TabView',
49-
subtitle: 'NestedScrollView example'.tr,
50-
icon: Icons.line_style,
48+
title: 'TabBarView',
49+
subtitle: 'TabBarView example'.tr,
50+
icon: Icons.tab_rounded,
5151
onTap: () => Get.toNamed(Routes.tabBarViewSample),
5252
),
5353
ListItem(

example/lib/page/sample/tab_bar_view_page.dart

+107-77
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class TabBarViewPageState extends State<TabBarViewPage>
4141
header: ClassicHeader(
4242
clamping: true,
4343
position: IndicatorPosition.locator,
44+
mainAxisAlignment: MainAxisAlignment.end,
4445
dragText: 'Pull to refresh'.tr,
4546
armedText: 'Release ready'.tr,
4647
readyText: 'Refreshing...'.tr,
@@ -88,94 +89,123 @@ class TabBarViewPageState extends State<TabBarViewPage>
8889
});
8990
},
9091
childBuilder: (context, physics) {
91-
return ExtendedNestedScrollView(
92-
physics: physics,
93-
onlyOneScrollInBody: true,
94-
pinnedHeaderSliverHeightBuilder: () {
95-
return MediaQuery.of(context).padding.top + kToolbarHeight;
96-
},
97-
headerSliverBuilder: (context, innerBoxIsScrolled) {
98-
return <Widget>[
99-
const HeaderLocator.sliver(clearExtent: false),
100-
SliverAppBar(
101-
expandedHeight: 166,
102-
pinned: true,
103-
flexibleSpace: FlexibleSpaceBar(
104-
title: Text(
105-
'TabBarView',
106-
style: TextStyle(
107-
color: Theme.of(context).textTheme.titleLarge?.color),
92+
return ScrollConfiguration(
93+
behavior: const ERScrollBehavior(),
94+
child: ExtendedNestedScrollView(
95+
physics: physics,
96+
onlyOneScrollInBody: true,
97+
pinnedHeaderSliverHeightBuilder: () {
98+
return MediaQuery.of(context).padding.top + kToolbarHeight;
99+
},
100+
headerSliverBuilder: (context, innerBoxIsScrolled) {
101+
return <Widget>[
102+
const HeaderLocator.sliver(clearExtent: false),
103+
SliverAppBar(
104+
expandedHeight: 120,
105+
pinned: true,
106+
flexibleSpace: FlexibleSpaceBar(
107+
title: Text(
108+
'TabBarView',
109+
style: TextStyle(
110+
color:
111+
Theme.of(context).textTheme.titleLarge?.color),
112+
),
113+
centerTitle: false,
108114
),
109-
titlePadding: const EdgeInsets.only(left: 64, bottom: 60),
110-
centerTitle: false,
111115
),
112-
bottom: PreferredSize(
113-
child: Padding(
114-
padding: const EdgeInsets.symmetric(
115-
horizontal: 8,
116+
];
117+
},
118+
body: Column(
119+
children: [
120+
TabBar(
121+
controller: _tabController,
122+
labelColor: themeData.colorScheme.primary,
123+
indicatorColor: themeData.colorScheme.primary,
124+
tabs: const <Widget>[
125+
Tab(
126+
text: 'List',
116127
),
117-
child: TabBar(
118-
controller: _tabController,
119-
labelColor: themeData.colorScheme.primary,
120-
indicatorColor: themeData.colorScheme.primary,
121-
tabs: const <Widget>[
122-
Tab(
123-
text: 'List',
124-
),
125-
Tab(
126-
text: 'Grid',
127-
),
128-
],
128+
Tab(
129+
text: 'Grid',
129130
),
130-
),
131-
preferredSize: const Size(double.infinity, 46),
132-
),
133-
),
134-
];
135-
},
136-
body: TabBarView(
137-
controller: _tabController,
138-
children: <Widget>[
139-
ExtendedVisibilityDetector(
140-
uniqueKey: const Key('Tab0'),
141-
child: CustomScrollView(
142-
physics: physics,
143-
slivers: [
144-
SliverList(
145-
delegate:
146-
SliverChildBuilderDelegate((context, index) {
147-
return const SkeletonItem();
148-
}, childCount: _listCount)),
149-
const FooterLocator.sliver(),
150131
],
151132
),
152-
),
153-
ExtendedVisibilityDetector(
154-
uniqueKey: const Key('Tab1'),
155-
child: CustomScrollView(
156-
physics: physics,
157-
slivers: [
158-
SliverGrid(
159-
delegate:
160-
SliverChildBuilderDelegate((context, index) {
161-
return const SkeletonItem(
162-
direction: Axis.horizontal,
163-
);
164-
}, childCount: _gridCount),
165-
gridDelegate:
166-
const SliverGridDelegateWithFixedCrossAxisCount(
167-
crossAxisCount: 2,
168-
childAspectRatio: 6 / 7,
169-
)),
170-
const FooterLocator.sliver(),
171-
],
133+
Expanded(
134+
child: TabBarView(
135+
controller: _tabController,
136+
children: <Widget>[
137+
ExtendedVisibilityDetector(
138+
uniqueKey: const Key('Tab0'),
139+
child: _AutomaticKeepAlive(
140+
child: CustomScrollView(
141+
physics: physics,
142+
slivers: [
143+
SliverList(
144+
delegate: SliverChildBuilderDelegate(
145+
(context, index) {
146+
return const SkeletonItem();
147+
}, childCount: _listCount)),
148+
const FooterLocator.sliver(),
149+
],
150+
),
151+
),
152+
),
153+
ExtendedVisibilityDetector(
154+
uniqueKey: const Key('Tab1'),
155+
child: _AutomaticKeepAlive(
156+
child: CustomScrollView(
157+
physics: physics,
158+
slivers: [
159+
SliverGrid(
160+
delegate: SliverChildBuilderDelegate(
161+
(context, index) {
162+
return const SkeletonItem(
163+
direction: Axis.horizontal,
164+
);
165+
}, childCount: _gridCount),
166+
gridDelegate:
167+
const SliverGridDelegateWithFixedCrossAxisCount(
168+
crossAxisCount: 2,
169+
childAspectRatio: 6 / 7,
170+
)),
171+
const FooterLocator.sliver(),
172+
],
173+
),
174+
),
175+
),
176+
],
177+
),
172178
),
173-
),
174-
],
179+
],
180+
),
175181
),
176182
);
177183
},
178184
),
179185
);
180186
}
181187
}
188+
189+
class _AutomaticKeepAlive extends StatefulWidget {
190+
final Widget child;
191+
192+
const _AutomaticKeepAlive({
193+
Key? key,
194+
required this.child,
195+
}) : super(key: key);
196+
197+
@override
198+
State<_AutomaticKeepAlive> createState() => _AutomaticKeepAliveState();
199+
}
200+
201+
class _AutomaticKeepAliveState extends State<_AutomaticKeepAlive>
202+
with AutomaticKeepAliveClientMixin {
203+
@override
204+
Widget build(BuildContext context) {
205+
super.build(context);
206+
return widget.child;
207+
}
208+
209+
@override
210+
bool get wantKeepAlive => true;
211+
}

example/lib/widget/skeleton_item.dart

+5-5
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class SkeletonItem extends StatelessWidget {
6565
}
6666
return Card(
6767
elevation: 0,
68-
color: Theme.of(context).colorScheme.surfaceVariant,
68+
color: backgroundColor,
6969
child: Padding(
7070
padding: const EdgeInsets.all(16),
7171
child: Column(
@@ -75,7 +75,7 @@ class SkeletonItem extends StatelessWidget {
7575
margin: const EdgeInsets.only(bottom: 16),
7676
height: 80,
7777
width: 80,
78-
color: Theme.of(context).splashColor,
78+
color: foregroundColor,
7979
),
8080
Expanded(
8181
child: Row(
@@ -88,19 +88,19 @@ class SkeletonItem extends StatelessWidget {
8888
constraints: const BoxConstraints(
8989
maxHeight: 200,
9090
),
91-
color: Theme.of(context).splashColor,
91+
color: foregroundColor,
9292
),
9393
Container(
9494
margin: const EdgeInsets.only(left: 16),
9595
width: 12,
9696
height: 80,
97-
color: Theme.of(context).splashColor,
97+
color: foregroundColor,
9898
),
9999
Container(
100100
margin: const EdgeInsets.only(left: 8),
101101
width: 12,
102102
height: 80,
103-
color: Theme.of(context).splashColor,
103+
color: foregroundColor,
104104
),
105105
],
106106
),

example/pubspec.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ description: EasyRefresh example.
77
# Both the version and the builder number may be overridden in flutter
88
# build by specifying --build-name and --build-number, respectively.
99
# Read more about versioning at semver.org.
10-
version: 3.0.2+47
10+
version: 3.0.3+48
1111

1212
environment:
1313
sdk: ">=2.13.0 <3.0.0"
@@ -31,7 +31,7 @@ dependencies:
3131
rive: ^0.9.0
3232
qr_flutter: ^4.0.0
3333
flutter_svg: ^1.1.1+1
34-
flutter_sticky_header: ^0.6.3
34+
flutter_sticky_header: ^0.6.4
3535
easy_refresh:
3636
path: ../
3737
easy_refresh_space:

example/windows/flutter/generated_plugin_registrant.cc

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66

77
#include "generated_plugin_registrant.h"
88

9-
#include <url_launcher_windows/url_launcher_windows.h>
9+
#include <url_launcher_windows/url_launcher_plugin.h>
1010

1111
void RegisterPlugins(flutter::PluginRegistry* registry) {
12-
UrlLauncherWindowsRegisterWithRegistrar(
13-
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
12+
UrlLauncherPluginRegisterWithRegistrar(
13+
registry->GetRegistrarForPlugin("UrlLauncherPlugin"));
1414
}

lib/src/behavior/scroll_behavior.dart

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ part of easy_refresh;
22

33
/// Define [ScrollBehavior] in the scope of EasyRefresh.
44
/// Add support for web and PC.
5-
class _ERScrollBehavior extends ScrollBehavior {
5+
class ERScrollBehavior extends ScrollBehavior {
66
final ScrollPhysics? _physics;
77

8-
const _ERScrollBehavior([this._physics]);
8+
const ERScrollBehavior([this._physics]);
99

1010
@override
1111
ScrollPhysics getScrollPhysics(BuildContext context) {
@@ -24,5 +24,6 @@ class _ERScrollBehavior extends ScrollBehavior {
2424
PointerDeviceKind.stylus,
2525
PointerDeviceKind.invertedStylus,
2626
PointerDeviceKind.mouse,
27+
PointerDeviceKind.unknown,
2728
};
2829
}

lib/src/easy_refresh.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -556,12 +556,12 @@ class _EasyRefreshState extends State<EasyRefresh>
556556
Widget child;
557557
if (widget.childBuilder != null) {
558558
child = ScrollConfiguration(
559-
behavior: const _ERScrollBehavior(),
559+
behavior: const ERScrollBehavior(),
560560
child: widget.childBuilder!(context, _physics),
561561
);
562562
} else {
563563
child = ScrollConfiguration(
564-
behavior: _ERScrollBehavior(_physics),
564+
behavior: ERScrollBehavior(_physics),
565565
child: widget.child!,
566566
);
567567
}

0 commit comments

Comments
 (0)