Skip to content

Commit

Permalink
Merge pull request #18 from fujidaiti/issue17
Browse files Browse the repository at this point in the history
Fix #17
  • Loading branch information
fujidaiti authored Apr 19, 2023
2 parents 995f592 + faf0b3e commit f5c381f
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 63 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
.history
.svn/
migrate_working_dir/
pubspeck.lock
pubspec.lock

6 changes: 3 additions & 3 deletions package/lib/src/core/controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ class _CurrentPageNotifier extends ValueNotifier<int> {
class ExprollablePageController extends PageController {
/// Create a page controller.
///
/// `snapViewportOffsets` is used to specify the viewport offsets that the active page will snap to.
/// [ViewportOffset.explored] and [ViewportOffset.shrunk] are set to be snaped by default.
/// If you specify additional offsets, you may need to also specify `maxViewportOffset`
/// `snapViewportOffsets` is used to specify the viewport offsets that the active page will snap to.
/// [ViewportOffset.explored] and [ViewportOffset.shrunk] are set to be snaped by default.
/// If you specify additional offsets, you may need to also specify `maxViewportOffset`
/// to be able to drag the page to the additional snap offsets larger than [ViewportOffset.shrunk].
ExprollablePageController({
super.initialPage,
Expand Down
92 changes: 33 additions & 59 deletions package/lib/src/internal/scroll.dart
Original file line number Diff line number Diff line change
Expand Up @@ -137,25 +137,14 @@ class AbsorbScrollPosition extends ScrollPositionWithSingleContext {
super.keepScrollOffset,
});

ScrollAbsorber? _absorber;

void attach(ScrollAbsorber absorber) {
if (identical(_absorber, absorber)) return;
_absorber = absorber;
if (hasPixels) correctPixels(pixels);
}

void detach(ScrollAbsorber absorber) {
if (!identical(_absorber, absorber)) return;
_absorber = null;
}
// May be initialized in [correctPixels] since it will be called
// in the super constructor if [initialPixels] is not null.
final ScrollAbsorber _absorber = ScrollAbsorber();

double get impliedPixels =>
_absorber?.pixels != null ? pixels - _absorber!.pixels! : pixels;
_absorber.pixels != null ? pixels - _absorber.pixels! : pixels;

double get impliedMinScrollExtent => _absorber != null
? minScrollExtent - _absorber!.capacity
: minScrollExtent;
double get impliedMinScrollExtent => minScrollExtent - _absorber.capacity;

static double _computeOverscroll(double pixels, double minScrollExtent) =>
max(0.0, minScrollExtent - pixels);
Expand All @@ -165,21 +154,14 @@ class AbsorbScrollPosition extends ScrollPositionWithSingleContext {

@override
bool applyContentDimensions(double minScrollExtent, double maxScrollExtent) {
if (_absorber == null) {
return super.applyContentDimensions(
minScrollExtent,
maxScrollExtent,
);
}

if (hasContentDimensions) {
return super.applyContentDimensions(minScrollExtent, maxScrollExtent);
} else {
// Once the viewport's content extents are established,
// we can calculate the initial overscroll from current [pixels]
// which is equal to [initialPixels] or [oldPosition.pixels] passed in the constructor.
// Then, initialize [OverscrollAbsorber] with the calculated overscroll.
_absorber!.correct((it) {
_absorber.correct((it) {
it.absorb(_computeOverscroll(pixels, minScrollExtent));
});
final oldPixels = pixels;
Expand Down Expand Up @@ -209,14 +191,17 @@ class AbsorbScrollPosition extends ScrollPositionWithSingleContext {
@override
void absorb(ScrollPosition other) {
super.absorb(other);
if (_absorber != null) {
if (other is AbsorbScrollPosition && other._absorber?.pixels != null) {
_absorber!.absorb(other._absorber!.pixels!);
} else if (hasPixels && hasContentDimensions) {
// `super.absorb(other)` may set `super._pixels` to
// an invalid value, which needs to be corrected.
correctPixels(pixels);
}
// if (other is AbsorbScrollPosition && other.absorber.pixels != null) {
// absorber.absorb(other.absorber.pixels!);
// } else if (hasPixels && hasContentDimensions) {
// // `super.absorb(other)` may set `super._pixels` to an invalid value,
// // which needs to be corrected.
// correctPixels(pixels);
// }
if (other.hasPixels && other is AbsorbScrollPosition) {
// `super.absorb(other)` may set `super._pixels` to an invalid value,
// which needs to be corrected.
correctPixels(other.impliedPixels);
}
}

Expand Down Expand Up @@ -255,13 +240,9 @@ class AbsorbScrollPosition extends ScrollPositionWithSingleContext {

@override
void correctPixels(double value) {
if (_absorber == null) {
super.correctPixels(value);
return;
}

if (hasPixels && value == impliedPixels) return;
if (hasContentDimensions) {
_absorber!.correct((it) {
_absorber.correct((it) {
it.absorb(_computeOverscroll(value, minScrollExtent));
});
super.correctPixels(_computeApparentPixels(value, minScrollExtent));
Expand All @@ -276,14 +257,9 @@ class AbsorbScrollPosition extends ScrollPositionWithSingleContext {

@override
void forcePixels(double value) {
if (_absorber == null) {
super.forcePixels(value);
return;
}

assert(hasPixels);
_impliedVelocity = value - impliedPixels;
_absorber!.absorb(_computeOverscroll(value, minScrollExtent));
_absorber.absorb(_computeOverscroll(value, minScrollExtent));
super.correctPixels(_computeApparentPixels(value, minScrollExtent));
notifyListeners();
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
Expand All @@ -308,14 +284,10 @@ class AbsorbScrollPosition extends ScrollPositionWithSingleContext {

@override
double setPixels(double newPixels) {
if (_absorber == null) {
return super.setPixels(newPixels);
}

if (newPixels == impliedPixels) return 0.0;
final unhandledOverscroll = applyBoundaryConditions(newPixels);
final newActualPixels = newPixels - unhandledOverscroll;
_absorber!.absorb(_computeOverscroll(newActualPixels, minScrollExtent));
_absorber.absorb(_computeOverscroll(newActualPixels, minScrollExtent));
super.setPixels(_computeApparentPixels(newActualPixels, minScrollExtent));
if (unhandledOverscroll != 0.0) {
didOverscrollBy(unhandledOverscroll);
Expand Down Expand Up @@ -382,17 +354,23 @@ class AbsorbScrollPosition extends ScrollPositionWithSingleContext {
@override
void jumpTo(double value) {
goIdle();
if (!impliedPixels.almostEqualTo(value)) {
if (impliedPixels.almostEqualTo(value)) {
final double oldPixels = pixels;
forcePixels(value);
didStartScroll();
if (!pixels.almostEqualTo(oldPixels)) {
if (pixels.almostEqualTo(oldPixels)) {
didUpdateScrollPositionBy(pixels - oldPixels);
}
didEndScroll();
}
goBallistic(0.0);
}

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

class AbsorbScrollController extends ScrollController {
Expand All @@ -401,9 +379,9 @@ class AbsorbScrollController extends ScrollController {
super.initialScrollOffset,
super.keepScrollOffset,
double absorberCapacity = 0.0,
}) : absorber = ScrollAbsorber(capacity: absorberCapacity);
}) : absorber = ScrollAbsorberGroup(capacity: absorberCapacity);

final ScrollAbsorber absorber;
final ScrollAbsorberGroup absorber;

@override
AbsorbScrollPosition get position => super.position as AbsorbScrollPosition;
Expand All @@ -428,23 +406,19 @@ class AbsorbScrollController extends ScrollController {
void attach(ScrollPosition position) {
super.attach(position);
assert(position is AbsorbScrollPosition);
(position as AbsorbScrollPosition).attach(absorber);
absorber.attach((position as AbsorbScrollPosition)._absorber);
}

@override
void detach(ScrollPosition position) {
super.detach(position);
assert(position is AbsorbScrollPosition);
(position as AbsorbScrollPosition).detach(absorber);
absorber.detach((position as AbsorbScrollPosition)._absorber);
}

@override
void dispose() {
super.dispose();
assert(positions.length <= 1);
if (hasClients) {
position.detach(absorber);
}
absorber.dispose();
}
}

0 comments on commit f5c381f

Please sign in to comment.