@@ -2,11 +2,8 @@ import 'dart:async';
2
2
import 'dart:collection' ;
3
3
import 'dart:developer' ;
4
4
import 'dart:math' as math;
5
- import 'dart:ui' ;
6
5
7
- import 'package:flutter/gestures.dart' ;
8
6
import 'package:flutter/rendering.dart' ;
9
- import 'package:flutter/scheduler.dart' ;
10
7
import 'package:flutter/widgets.dart' ;
11
8
import 'package:vector_math/vector_math_64.dart' ;
12
9
@@ -269,6 +266,8 @@ class PageListViewportController with ChangeNotifier {
269
266
// Jump to the desired page on viewport attachment.
270
267
_origin = _getPageOffset (_initialPageIndex! );
271
268
_initialPageIndex = null ;
269
+ } else {
270
+ _origin = _constrainOriginToViewportBounds (_origin);
272
271
}
273
272
}
274
273
@@ -495,20 +494,35 @@ class PageListViewportController with ChangeNotifier {
495
494
}
496
495
497
496
Offset _constrainOriginToViewportBounds (Offset desiredOrigin) {
498
- final totalContentHeight = _viewport! .calculateContentHeight (scale);
499
- if (totalContentHeight >= _viewport! .size.height) {
500
- // Content is as tall, or taller than the viewport.
501
- return Offset (
502
- desiredOrigin.dx.clamp (_viewport! .size.width - _viewport! .calculatePageWidth (scale), 0.0 ),
503
- desiredOrigin.dy.clamp (- _viewport! .calculateContentHeight (scale) + _viewport! .size.height, 0.0 ),
504
- );
497
+ // If content is thinner than a viewport dimension, that content should be centered.
498
+ //
499
+ // If content is as wide, or wider than a viewport dimension, that content offset should
500
+ // be constrained so that no white space ever appears on either side of the content along
501
+ // that dimension.
502
+ double originX = desiredOrigin.dx;
503
+ double originY = desiredOrigin.dy;
504
+
505
+ final contentWidth = _viewport! .calculatePageWidth (scale);
506
+ final contentHeight = _viewport! .calculateContentHeight (scale);
507
+ final viewportSize = _viewport! .size;
508
+
509
+ if (contentWidth <= viewportSize.width) {
510
+ originX = (viewportSize.width - contentWidth) / 2 ;
505
511
} else {
506
- // Content is shorter than the viewport.
507
- return Offset (
508
- desiredOrigin.dx.clamp (_viewport! .size.width - _viewport! .calculatePageWidth (scale), 0.0 ),
509
- (_viewport! .size.height - totalContentHeight) / 2 ,
510
- );
512
+ const maxOriginX = 0.0 ;
513
+ final minOriginX = viewportSize.width - contentWidth;
514
+ originX = originX.clamp (minOriginX, maxOriginX);
511
515
}
516
+
517
+ if (contentHeight <= viewportSize.height) {
518
+ originY = (viewportSize.height - contentHeight) / 2 ;
519
+ } else {
520
+ const maxOriginY = 0.0 ;
521
+ final minOriginY = viewportSize.height - contentHeight;
522
+ originY = originY.clamp (minOriginY, maxOriginY);
523
+ }
524
+
525
+ return Offset (originX, originY);
512
526
}
513
527
}
514
528
@@ -712,7 +726,11 @@ class RenderPageListViewport extends RenderBox {
712
726
}
713
727
714
728
_minimumScaleToFillViewport = size.width / _naturalPageSize.width;
729
+
730
+ // Set the private property, directly, so that we don't try to markNeedsLayout during
731
+ // layout.
715
732
_controller! ._minimumScale = _minimumScaleToFillViewport;
733
+
716
734
if (_isFirstLayoutForController && _pageCount > 0 ) {
717
735
_controller! ._scale = _minimumScaleToFillViewport;
718
736
@@ -726,6 +744,9 @@ class RenderPageListViewport extends RenderBox {
726
744
}
727
745
728
746
_isFirstLayoutForController = false ;
747
+ } else if (_controller! .scale < _minimumScaleToFillViewport) {
748
+ // Update the private property so that we don't markNeedsLayout during layout.
749
+ _controller! ._scale = _minimumScaleToFillViewport;
729
750
}
730
751
731
752
// We must let the controller do its layout work before we create and cull the pages,
0 commit comments