Skip to content

Commit 91f5104

Browse files
Report page list velocity when animating page offset (Resolves #27) (#29)
1 parent 7f5b7b1 commit 91f5104

File tree

2 files changed

+100
-60
lines changed

2 files changed

+100
-60
lines changed

example/lib/main_list.dart

Lines changed: 72 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ class MyHomePage extends StatefulWidget {
3333
}
3434

3535
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
36+
static const _pageCount = 20;
37+
static const _naturalPageSizeInInches = Size(8.5, 11);
38+
3639
late final PageListViewportController _controller;
3740

3841
@override
@@ -50,51 +53,81 @@ class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateM
5053
@override
5154
Widget build(BuildContext context) {
5255
return Scaffold(
53-
body: PageListViewportGestures(
56+
body: Row(
57+
crossAxisAlignment: CrossAxisAlignment.stretch,
58+
children: [
59+
SizedBox(
60+
width: 125,
61+
child: _buildThumbnailList(),
62+
),
63+
Expanded(
64+
child: _buildViewport(),
65+
),
66+
],
67+
),
68+
);
69+
}
70+
71+
Widget _buildViewport() {
72+
return PageListViewportGestures(
73+
controller: _controller,
74+
lockPanAxis: true,
75+
child: PageListViewport(
5476
controller: _controller,
55-
lockPanAxis: true,
56-
child: PageListViewport(
57-
controller: _controller,
58-
pageCount: 60, //_pageCount,
59-
naturalPageSize: const Size(8.5, 11) * 72 * MediaQuery.of(context).devicePixelRatio,
60-
pageLayoutCacheCount: 3,
61-
pagePaintCacheCount: 3,
62-
builder: (BuildContext context, int pageIndex) {
63-
return Stack(
64-
children: [
65-
Positioned.fill(
66-
child: Image.asset(
67-
"assets/test-image.jpeg",
68-
fit: BoxFit.cover,
69-
),
77+
pageCount: _pageCount,
78+
naturalPageSize: _naturalPageSizeInInches * 72 * MediaQuery.of(context).devicePixelRatio,
79+
pageLayoutCacheCount: 3,
80+
pagePaintCacheCount: 3,
81+
builder: (BuildContext context, int pageIndex) {
82+
return Stack(
83+
children: [
84+
Positioned.fill(
85+
child: _buildPage(pageIndex),
86+
),
87+
Center(
88+
child: Container(
89+
padding: const EdgeInsets.all(32),
90+
color: Colors.white,
91+
child: Text("Page: $pageIndex"),
7092
),
71-
Center(
72-
child: Container(
73-
padding: const EdgeInsets.all(32),
74-
color: Colors.white,
75-
child: Text("Page: $pageIndex"),
76-
),
77-
)
78-
],
79-
);
93+
)
94+
],
95+
);
96+
},
97+
),
98+
);
99+
}
80100

81-
// return RepaintBoundary(
82-
// key: ValueKey(pageIndex),
83-
// child: Container(
84-
// width: double.infinity,
85-
// height: double.infinity,
86-
// decoration: const BoxDecoration(
87-
// gradient: LinearGradient(
88-
// colors: [Colors.red, Colors.blue],
89-
// begin: Alignment.topLeft,
90-
// end: Alignment.bottomRight,
91-
// ),
92-
// ),
93-
// ),
94-
// );
101+
Widget _buildThumbnailList() {
102+
return RepaintBoundary(
103+
child: ColoredBox(
104+
color: Colors.grey.shade800,
105+
child: ListView.builder(
106+
padding: const EdgeInsets.all(16),
107+
itemCount: _pageCount,
108+
itemBuilder: (context, index) {
109+
return Padding(
110+
padding: const EdgeInsets.symmetric(vertical: 8),
111+
child: GestureDetector(
112+
onTap: () {
113+
_controller.animateToPage(index, const Duration(milliseconds: 250));
114+
},
115+
child: AspectRatio(
116+
aspectRatio: _naturalPageSizeInInches.aspectRatio,
117+
child: _buildPage(index),
118+
),
119+
),
120+
);
95121
},
96122
),
97123
),
98124
);
99125
}
126+
127+
Widget _buildPage(int pageIndex) {
128+
return Image.asset(
129+
"assets/test-image.jpeg",
130+
fit: BoxFit.cover,
131+
);
132+
}
100133
}

lib/src/page_list_viewport.dart

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,18 @@ class PageListViewportController with ChangeNotifier {
143143

144144
void _initController(TickerProvider vsync) {
145145
_animationController = AnimationController(vsync: vsync) //
146-
..addListener(_onOrientationAnimationChange);
146+
..addListener(_onOrientationAnimationChange)
147+
..addStatusListener((status) {
148+
switch (status) {
149+
case AnimationStatus.dismissed:
150+
case AnimationStatus.completed:
151+
_onOrientationAnimationEnd();
152+
break;
153+
case AnimationStatus.forward:
154+
case AnimationStatus.reverse:
155+
break;
156+
}
157+
});
147158

148159
_velocityStopwatch.start();
149160
_scaleVelocityStopwatch.start();
@@ -352,9 +363,6 @@ class PageListViewportController with ChangeNotifier {
352363
return Future.value();
353364
}
354365

355-
// Stop any on-going orientation animation so we can start a new one.
356-
_animationController.stop();
357-
358366
final centerOfPage = _viewport!.calculatePageSize(1.0).center(Offset.zero);
359367
return animateToOffsetInPage(pageIndex, centerOfPage, duration);
360368
}
@@ -394,25 +402,10 @@ class PageListViewportController with ChangeNotifier {
394402
_constrainOriginToViewportBounds(Offset(0, -contentAboveDesiredPage) + desiredPageTopLeftInViewport);
395403

396404
_previousOrigin = _origin;
405+
_velocityStopwatch.reset();
397406
_offsetAnimation = Tween<Offset>(begin: _origin, end: destinationOffset).animate(
398407
CurvedAnimation(parent: _animationController, curve: curve),
399-
)
400-
..addListener(() {
401-
_velocity = _offsetAnimation!.value - _previousOrigin;
402-
_previousOrigin = _offsetAnimation!.value;
403-
})
404-
..addStatusListener((status) {
405-
switch (status) {
406-
case AnimationStatus.dismissed:
407-
case AnimationStatus.completed:
408-
_velocity = Offset.zero;
409-
break;
410-
case AnimationStatus.forward:
411-
case AnimationStatus.reverse:
412-
// Don't care.
413-
break;
414-
}
415-
});
408+
);
416409

417410
_scaleAnimation = Tween<double>(begin: scale, end: desiredZoomLevel).animate(
418411
CurvedAnimation(parent: _animationController, curve: curve),
@@ -428,6 +421,20 @@ class PageListViewportController with ChangeNotifier {
428421
void _onOrientationAnimationChange() {
429422
_origin = _offsetAnimation!.value;
430423
_scale = _scaleAnimation!.value;
424+
425+
if (_velocityStopwatch.elapsedMilliseconds > 0) {
426+
_velocity = (_offsetAnimation!.value - _previousOrigin) / (_velocityStopwatch.elapsedMilliseconds / 1000);
427+
_velocityStopwatch.reset();
428+
}
429+
_previousOrigin = _offsetAnimation!.value;
430+
431+
notifyListeners();
432+
}
433+
434+
void _onOrientationAnimationEnd() {
435+
_velocity = Offset.zero;
436+
_velocityStopwatch.reset();
437+
431438
notifyListeners();
432439
}
433440

0 commit comments

Comments
 (0)