Skip to content

Commit 01a590e

Browse files
Fix origin clamping (Resolves #25) (#26)
1 parent 87829c5 commit 01a590e

File tree

2 files changed

+37
-15
lines changed

2 files changed

+37
-15
lines changed

example/lib/main_single_page_orientation.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateM
5858
controller: _controller,
5959
pageCount: 1,
6060
naturalPageSize: const Size(8.5, 11) * 72 * MediaQuery.of(context).devicePixelRatio,
61+
// naturalPageSize: const Size(11, 8.5) * 72 * MediaQuery.of(context).devicePixelRatio,
6162
builder: (BuildContext context, int pageIndex) {
6263
return Stack(
6364
children: [

lib/src/page_list_viewport.dart

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,8 @@ import 'dart:async';
22
import 'dart:collection';
33
import 'dart:developer';
44
import 'dart:math' as math;
5-
import 'dart:ui';
65

7-
import 'package:flutter/gestures.dart';
86
import 'package:flutter/rendering.dart';
9-
import 'package:flutter/scheduler.dart';
107
import 'package:flutter/widgets.dart';
118
import 'package:vector_math/vector_math_64.dart';
129

@@ -269,6 +266,8 @@ class PageListViewportController with ChangeNotifier {
269266
// Jump to the desired page on viewport attachment.
270267
_origin = _getPageOffset(_initialPageIndex!);
271268
_initialPageIndex = null;
269+
} else {
270+
_origin = _constrainOriginToViewportBounds(_origin);
272271
}
273272
}
274273

@@ -495,20 +494,35 @@ class PageListViewportController with ChangeNotifier {
495494
}
496495

497496
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;
505511
} 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);
511515
}
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);
512526
}
513527
}
514528

@@ -712,7 +726,11 @@ class RenderPageListViewport extends RenderBox {
712726
}
713727

714728
_minimumScaleToFillViewport = size.width / _naturalPageSize.width;
729+
730+
// Set the private property, directly, so that we don't try to markNeedsLayout during
731+
// layout.
715732
_controller!._minimumScale = _minimumScaleToFillViewport;
733+
716734
if (_isFirstLayoutForController && _pageCount > 0) {
717735
_controller!._scale = _minimumScaleToFillViewport;
718736

@@ -726,6 +744,9 @@ class RenderPageListViewport extends RenderBox {
726744
}
727745

728746
_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;
729750
}
730751

731752
// We must let the controller do its layout work before we create and cull the pages,

0 commit comments

Comments
 (0)