Skip to content

Commit

Permalink
Make stretching behavior of StretchingSheetPhysics more customizable (#…
Browse files Browse the repository at this point in the history
…171)

Closes #159.

## Breaking Changes
- Removed the `StretchingSheetPhysics.stretchingRange` property.
- Added `StretchingBehavior` and its subclasses as the replacements.
- `FixedStretchingBehavior`: Allows a sheet to stretch by up to a fixed
amount.
- `DirectionAwareStretchingBehavior`: Similar to
`FixedStretchingBehavior`, but can accept different values for upward
and downward directions.

## Misc
- Added the migration guide.
- Updated README and CHANGELOG.
  • Loading branch information
fujidaiti authored Jun 16, 2024
1 parent fc28743 commit fac4c42
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 16 deletions.
30 changes: 30 additions & 0 deletions docs/migration-guide-0.8.x.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Migration guide to 0.8.x from 0.7.x

Here is the summary of the breaking changes included in the version 0.8.0.

## Changes in StretchingSheetPhysics

### New way to control the stretching behavior of a sheet

[StretchingSheetBehavior](https://pub.dev/documentation/smooth_sheets/latest/smooth_sheets/StretchingSheetBehavior-class.html) was added as the new way to control the stretching behavior of a sheet. It replaces `StretchingSheetPhysics.stretchingRange` property, which has been removed.

**BEFORE:**

```dart
const physics = StretchingSheetPhysics(
stretchingRange: Extent.proportional(0.1),
);
```

**AFTER:**

```dart
const physics = StretchingSheetPhysics(
behavior: FixedStretchingBehavior(Extent.proportional(0.1)),
);
```

See also:

- [FixedStretchingBehavior](https://pub.dev/documentation/smooth_sheets/latest/smooth_sheets/FixedStretchingBehavior-class.html), which stretches the sheet by a fixed amount.
- [DirectionAwareStretchingBehavior](https://pub.dev/documentation/smooth_sheets/latest/smooth_sheets/DirectionAwareStretchingBehavior-class.html), which stretches the sheet by a fixed amount, based on the direction of a drag.
6 changes: 6 additions & 0 deletions package/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 0.8.x

This version contains some breaking changes. See the [migration guide](https://github.com/fujidaiti/smooth_sheets/blob/main/docs/migration-guide-0.8.x.md) for more details.

- Make stretching behavior of StretchingSheetPhysics more customizable (#171)

## 0.7.3 Jun 9, 2024

- Fix: DropdownButton doesn't work in NavigationSheet (#139)
Expand Down
4 changes: 2 additions & 2 deletions package/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ This library is currently in the experimental stage. The API may undergo changes

## Migration guide

- [0.6.x to 0.7.x](https://github.com/fujidaiti/smooth_sheets/blob/main/docs/migration-guide-0.7.x.md) 🆕
- [0.5.x to 0.6.x](https://github.com/fujidaiti/smooth_sheets/blob/main/docs/migration-guide-0.6.x.md)
- [0.7.x to 0.8.x](https://github.com/fujidaiti/smooth_sheets/blob/main/docs/migration-guide-0.8.x.md) 🆕
- [0.6.x to 0.7.x](https://github.com/fujidaiti/smooth_sheets/blob/main/docs/migration-guide-0.7.x.md)

See [here](https://github.com/fujidaiti/smooth_sheets/blob/main/docs/) for older versions.

Expand Down
3 changes: 3 additions & 0 deletions package/lib/src/foundation/foundation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,16 @@ export 'sheet_notification.dart'
export 'sheet_physics.dart'
show
ClampingSheetPhysics,
DirectionAwareStretchingBehavior,
FixedStretchingBehavior,
InterpolationSimulation,
SheetPhysics,
SheetPhysicsMixin,
SnapToNearest,
SnapToNearestEdge,
SnappingSheetBehavior,
SnappingSheetPhysics,
StretchingBehavior,
StretchingSheetPhysics,
kDefaultSheetPhysics,
kDefaultSheetSpring;
Expand Down
112 changes: 98 additions & 14 deletions package/lib/src/foundation/sheet_physics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,8 @@ mixin _SnapToNearestMixin implements SnappingSheetBehavior {
/// it will snap to [SheetMetrics.maxPixels].
///
/// Using this behavior is functionally identical to using [SnapToNearest]
/// with the snap positions of [SheetExtentConfig.minExtent] and
/// [SheetExtentConfig.maxExtent], but more simplified and efficient.
/// with the snap positions of [SheetExtent.minExtent] and
/// [SheetExtent.maxExtent], but more simplified and efficient.
class SnapToNearestEdge with _SnapToNearestMixin {
/// Creates a [SnappingSheetBehavior] that snaps to either
/// [SheetMetrics.minPixels] or [SheetMetrics.maxPixels].
Expand Down Expand Up @@ -378,15 +378,100 @@ class ClampingSheetPhysics extends SheetPhysics with SheetPhysicsMixin {
}
}

/// An object that determines the behavior of a sheet when it is out of bounds.
///
/// See also:
/// - [FixedStretchingBehavior], which stretches the sheet by a fixed amount.
/// - [DirectionAwareStretchingBehavior], which stretches the sheet based on the
/// direction of a drag.
abstract class StretchingBehavior {
/// Returns the number of pixels the sheet can stretch beyond the content
/// bounds.
///
/// [StretchingSheetPhysics.applyPhysicsToOffset] calls this method to
/// determine how many pixels the sheet can stretch beyond the content bounds.
/// The returned value must be non-negative.
///
/// The [offset] is the amount of pixels that will be applied to the sheet,
/// and [metrics] is the current metrics of the sheet.
double computeStretchablePixels(double offset, SheetMetrics metrics);
}

/// A [StretchingBehavior] that stretches the sheet by a fixed amount.
///
/// The following is an example of a [StretchingSheetPhysics] that allows the
/// sheet to stretch by 12% of the content size.
/// ```dart
/// const physics = StretchingSheetPhysics(
/// behavior: FixedStretchingBehavior(Extent.proportional(0.12)),
/// );
/// ```
class FixedStretchingBehavior implements StretchingBehavior {
/// Creates a [StretchingBehavior] that stretches the sheet by a fixed amount.
const FixedStretchingBehavior(this.range);

/// How much the sheet can stretch beyond the content bounds.
final Extent range;

@override
double computeStretchablePixels(double offset, SheetMetrics metrics) {
return range.resolve(metrics.contentSize);
}
}

/// A [StretchingBehavior] that stretches the sheet by a fixed amount.
///
/// Different stretching ranges can be specified for upward and downward
/// directions. For example, the following [StretchingSheetPhysics] allows the
/// sheet to stretch by 12% of the content size when dragged downward, and by
/// 8 pixels when dragged upward.
///
/// ```dart
/// const physics = StretchingSheetPhysics(
/// behavior: DirectionAwareStretchingBehavior(
/// upward: Extent.pixels(8),
/// downward: Extent.proportional(0.12),
/// ),
/// );
/// ```
class DirectionAwareStretchingBehavior implements StretchingBehavior {
/// Creates a [StretchingBehavior] that stretches the sheet by a fixed amount
/// based on the direction of a drag.
const DirectionAwareStretchingBehavior({
this.upward = const Extent.pixels(0),
this.downward = const Extent.pixels(0),
});

/// How much the sheet can stretch beyond the content bounds when dragged
/// upward.
final Extent upward;

/// How much the sheet can stretch beyond the content bounds when dragged
/// downward.
final Extent downward;

@override
double computeStretchablePixels(double offset, SheetMetrics metrics) {
return switch (offset) {
> 0.0 => upward.resolve(metrics.contentSize),
< 0.0 => downward.resolve(metrics.contentSize),
_ => 0.0,
};
}
}

class StretchingSheetPhysics extends SheetPhysics with SheetPhysicsMixin {
const StretchingSheetPhysics({
super.parent,
this.stretchingRange = const Extent.proportional(0.12),
this.behavior = const FixedStretchingBehavior(Extent.proportional(0.12)),
this.frictionCurve = Curves.easeOutSine,
this.spring = kDefaultSheetSpring,
});

final Extent stretchingRange;
/// The behavior that determines how the sheet stretches when it is
/// out of the content bounds.
final StretchingBehavior behavior;

final Curve frictionCurve;

@override
Expand All @@ -397,29 +482,34 @@ class StretchingSheetPhysics extends SheetPhysics with SheetPhysicsMixin {
SheetPhysics? parent,
SpringDescription? spring,
Extent? stretchingRange,
StretchingBehavior? behavior,
Curve? frictionCurve,
}) {
return StretchingSheetPhysics(
parent: parent ?? this.parent,
spring: spring ?? this.spring,
stretchingRange: stretchingRange ?? this.stretchingRange,
behavior: behavior ?? this.behavior,
frictionCurve: frictionCurve ?? this.frictionCurve,
);
}

@override
double computeOverflow(double offset, SheetMetrics metrics) {
final stretchingRange = this.stretchingRange.resolve(metrics.contentSize);

final stretchingRange = behavior.computeStretchablePixels(offset, metrics);
if (stretchingRange != 0) {
return 0;
return const ClampingSheetPhysics().applyPhysicsToOffset(offset, metrics);
}

return super.computeOverflow(offset, metrics);
}

@override
double applyPhysicsToOffset(double offset, SheetMetrics metrics) {
final stretchingRange = behavior.computeStretchablePixels(offset, metrics);
if (stretchingRange == 0) {
return const ClampingSheetPhysics().applyPhysicsToOffset(offset, metrics);
}

final currentPixels = metrics.pixels;
final minPixels = metrics.minPixels;
final maxPixels = metrics.maxPixels;
Expand All @@ -432,12 +522,6 @@ class StretchingSheetPhysics extends SheetPhysics with SheetPhysicsMixin {
return offset;
}

final stretchingRange = this.stretchingRange.resolve(metrics.contentSize);

if (stretchingRange.isApprox(0)) {
return 0;
}

// We divide the delta into smaller fragments
// and apply friction to each fragment in sequence.
// This ensures that the friction is not too small
Expand Down

0 comments on commit fac4c42

Please sign in to comment.