Skip to content

Commit

Permalink
Allow to choose dragging and paging animations #minor
Browse files Browse the repository at this point in the history
  • Loading branch information
fermoya committed Apr 15, 2021
1 parent 4c88486 commit 80a31d0
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 28 deletions.
2 changes: 1 addition & 1 deletion Documentation/Usage.md
Expand Up @@ -227,7 +227,7 @@ Transform your `Pager` into an endless sroll by using `loopPages`:

## Page Transitions

Use `draggingAnimation(_:)` to customize the _transition_ to the next page.
Use `draggingAnimation(onChange:, onEnded:)` to customize the animations applied while dragging items and/or transitioning to the next element.

```swift
Pager(...)
Expand Down
9 changes: 6 additions & 3 deletions Sources/SwiftUIPager/PageConfiguration/PagingAnimation.swift
Expand Up @@ -33,7 +33,7 @@ public enum PagingAnimation: Equatable {
/// Pass your custom animation
///
/// - Parameter animation: animation to be applied
case custom(animation: Animation)
case custom(animation: Animation?)

/// Standard animation. Single pagination `Pager` defaults to this value. Ease-out, 0.35 seconds.
public static var standard: PagingAnimation = .standard(duration: 0.35)
Expand All @@ -42,15 +42,18 @@ public enum PagingAnimation: Equatable {
/// See the bezier curve [here](https://cubic-bezier.com/#.2,1,.9,1).
public static var steep: PagingAnimation = .steep(duration: 0.2)

/// No animation applied
public static var none: PagingAnimation = .custom(animation: nil)

/// Translates the option selected to a `SwiftUI` animation
var animation: Animation {
var animation: Animation? {
switch self {
case .steep(let duration):
return Animation.timingCurve(0.2, 1, 0.9, 1, duration: duration)
case .standard(let duration):
return Animation.easeOut(duration: duration)
case .interactive:
return .interactiveSpring(response: 0.3, dampingFraction: 0.8, blendDuration: 0.5)
return .interactiveSpring()
case .custom(let animation):
return animation
}
Expand Down
20 changes: 17 additions & 3 deletions Sources/SwiftUIPager/Pager+Buildable.swift
Expand Up @@ -70,13 +70,27 @@ extension Pager: Buildable {

#if !os(tvOS)

/// Sets the explicit animation used for dragging
/// Sets the explicit animation to be used. Defaults to `.standard`
///
/// - Parameter value: explicit animation
public func draggingAnimation(_ value: DraggingAnimation?) -> Self {
/// - Parameter value: animation to use while dragging and to page
///
/// - Warning: `spring` animations don't work well. Avoid high responses while dragging as the animation should be short
public func draggingAnimation(_ value: DraggingAnimation) -> Self {
mutating(keyPath: \.draggingAnimation, value: value)
}

/// Sets the explicit animation to be used. Defaults to `.standard`
///
/// - Parameter anim1: animation to use while dragging
/// - Parameter anim2: animation to use to page
///
/// - Note: Setting different animations could cause unexpected behavior
/// - Warning: `spring` animations don't work well. Avoid high responses while dragging as the animation should be short
public func draggingAnimation(onChange anim1: DraggingAnimation, onEnded anim2: DraggingAnimation) -> Self {
mutating(keyPath: \.draggingAnimation, value: anim1)
.mutating(keyPath: \.pagingAnimation, value: { _ in anim2 })
}

/// Sensitivity used to determine whether or not to swipe the page
///
/// - Parameter value: sensitivity to be applied when paginating
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftUIPager/Pager.swift
Expand Up @@ -73,7 +73,7 @@ public struct Pager<Element, ID, PageView>: View where PageView: View, Element:
var pagingAnimation: ((DragResult) -> PagingAnimation)?

/// Animation used for dragging
var draggingAnimation: DraggingAnimation?
var draggingAnimation: DraggingAnimation = .standard

/// Sensitivity used to determine whether or not to swipe the page
var sensitivity: PaginationSensitivity = .default
Expand Down
20 changes: 17 additions & 3 deletions Sources/SwiftUIPager/PagerContent+Buildable.swift
Expand Up @@ -70,13 +70,27 @@ extension Pager.PagerContent: Buildable {

#if !os(tvOS)

/// Sets the explicit animation used for dragging
/// Sets the explicit animation to be used. Defaults to `.standard`
///
/// - Parameter value: explicit animation
func draggingAnimation(_ value: DraggingAnimation?) -> Self {
/// - Parameter value: animation to use while dragging and to page
///
/// - Warning: `spring` animations don't work well. Avoid high responses while dragging as the animation should be short
func draggingAnimation(_ value: DraggingAnimation) -> Self {
mutating(keyPath: \.draggingAnimation, value: value)
}

/// Sets the explicit animation to be used. Defaults to `.standard`
///
/// - Parameter anim1: animation to use while dragging
/// - Parameter anim2: animation to use to page
///
/// - Note: Setting different animations could cause unexpected behavior
/// - Warning: `spring` animations don't work well. Avoid high responses while dragging as the animation should be short
func draggingAnimation(onChange anim1: DraggingAnimation, onEnded anim2: DraggingAnimation) -> Self {
mutating(keyPath: \.draggingAnimation, value: anim1)
.mutating(keyPath: \.pagingAnimation, value: { _ in anim2 })
}

/// Sensitivity used to determine whether or not to swipe the page
///
/// - Parameter value: sensitivity to be applied when paginating
Expand Down
8 changes: 4 additions & 4 deletions Sources/SwiftUIPager/PagerContent.swift
Expand Up @@ -57,7 +57,7 @@ extension Pager {
var pagingAnimation: ((DragResult) -> PagingAnimation)?

/// Animation used for dragging
var draggingAnimation: DraggingAnimation?
var draggingAnimation: DraggingAnimation = .standard

/// Sensitivity used to determine whether or not to swipe the page
var sensitivity: PaginationSensitivity = .default
Expand Down Expand Up @@ -225,7 +225,7 @@ extension Pager.PagerContent {
}

func onDragChanged(with value: DragGesture.Value) {
let animation = draggingAnimation?.animation ?? .default
let animation = draggingAnimation.animation
withAnimation(animation) {
if self.lastDraggingValue == nil {
onDraggingBegan?()
Expand Down Expand Up @@ -280,9 +280,9 @@ extension Pager.PagerContent {
speed = 1 / min(4, Double(pageIncrement))
}

let pagingAnimation = self.draggingAnimation ?? self.pagingAnimation?((page, newPage, draggingOffset, draggingVelocity)) ?? defaultPagingAnimation
let pagingAnimation = self.pagingAnimation?((page, newPage, draggingOffset, draggingVelocity)) ?? defaultPagingAnimation

let animation = pagingAnimation.animation.speed(speed)
let animation = pagingAnimation.animation?.speed(speed)
if page != newPage {
onPageWillChange?(newPage)
}
Expand Down
13 changes: 12 additions & 1 deletion Tests/SwiftUIPagerTests/Pager+Buildable_Tests.swift
Expand Up @@ -35,7 +35,7 @@ final class Pager_Buildable_Tests: XCTestCase {
XCTAssertEqual(pager.contentLoadingPolicy, .default)
XCTAssertEqual(pager.allowsMultiplePagination, false)
XCTAssertNil(pager.pagingAnimation)
XCTAssertNil(pager.draggingAnimation)
XCTAssertEqual(pager.draggingAnimation, PagingAnimation.standard)
XCTAssertEqual(pager.sensitivity, .default)
XCTAssertEqual(pager.pageRatio, 1)
XCTAssertTrue(pager.bounces)
Expand Down Expand Up @@ -122,6 +122,16 @@ final class Pager_Buildable_Tests: XCTestCase {
XCTAssertEqual(animation, PagingAnimation.steep)
}

func test_GivenPager_WhenDraggingAnimation_ThenDraggingAndPagingAnimationNotNil() throws {
var pager = givenPager
pager = pager.draggingAnimation(onChange: .interactive, onEnded: .steep)
let pagerContent = pager.content(for: CGSize(width: 100, height: 100))
let anim1 = try XCTUnwrap(pagerContent.draggingAnimation)
let anim2 = try XCTUnwrap(pagerContent.pagingAnimation?((0, 0, 0, 0)))
XCTAssertEqual(anim1, PagingAnimation.interactive)
XCTAssertEqual(anim2, PagingAnimation.steep)
}

func test_GivenPager_WhenMultiplePagination_ThenAllowsMultiplePagination() {
var pager = givenPager
pager = pager.multiplePagination()
Expand Down Expand Up @@ -617,6 +627,7 @@ final class Pager_Buildable_Tests: XCTestCase {
("test_GivenPagerWith3DRotation_WhenInteractive_ThenInteractiveScaleNotChanged", test_GivenPagerWith3DRotation_WhenInteractive_ThenInteractiveScaleNotChanged),
("test_GivenPager_When3DRotation_ThenShouldRotate", test_GivenPager_When3DRotation_ThenShouldRotate),
("test_GivenPagerWith3DRotation_When3DRotationFalse_ThenShouldRotateFalse", test_GivenPagerWith3DRotation_When3DRotationFalse_ThenShouldRotateFalse),
("test_GivenPager_WhenDraggingAnimation_ThenDraggingAndPagingAnimationNotNil", test_GivenPager_WhenDraggingAnimation_ThenDraggingAndPagingAnimationNotNil),
("test_GivenPager_WhenDraggingAnimation_ThenDraggingAnimationNotNil", test_GivenPager_WhenDraggingAnimation_ThenDraggingAnimationNotNil),
("test_GivenPager_WhenHorizontalRightToLeft_ThenScrollAngle", test_GivenPager_WhenHorizontalRightToLeft_ThenScrollAngle),
("test_GivenPager_WhenAlignment_ThenAlignmentSet", test_GivenPager_WhenAlignment_ThenAlignmentSet),
Expand Down
7 changes: 6 additions & 1 deletion Tests/SwiftUIPagerTests/PagingAnimation_Tests.swift
Expand Up @@ -31,12 +31,17 @@ final class PagingAnimation_Tests: XCTestCase {
}

func test_GivenPagingAnimationInteractive_WhenAnimation_ThenExpectedAnimationValues() {
let input = Animation.interactiveSpring(response: 0.3, dampingFraction: 0.8, blendDuration: 0.5)
let input = Animation.interactiveSpring()
let pagingAnimation: PagingAnimation = .interactive
let animation = pagingAnimation.animation
XCTAssertEqual(animation, input)
}

func test_GivenPagingAnimationNone_WhenAnimation_ThenNil() {
let pagingAnimation: PagingAnimation = .none
XCTAssertNil(pagingAnimation.animation)
}

static var allTests = [
("test_GivenPagingAnimationSteep_WhenAnimation_ThenExpectedAnimationValues", test_GivenPagingAnimationSteep_WhenAnimation_ThenExpectedAnimationValues),
("test_GivenPagingAnimationStandard_WhenAnimation_ThenExpectedAnimationValues", test_GivenPagingAnimationStandard_WhenAnimation_ThenExpectedAnimationValues),
Expand Down
14 changes: 3 additions & 11 deletions release_description.md
@@ -1,14 +1,6 @@
### Features
- New `interactive(opacity:)` to add an interactive fade in/out effect to the scroll
- New `interactive(scale:)` and `interactive(rotation:)`
- Interactive effects can be now combined
- CI/CD to build `legacy-projects` branch against _iOS 12_

### Fixes
- Items not scrolling in _iOS 13_
- #193 Transitions are jumpy if fast
- #194 `AnimatableModifier` symbol not found
- New `dragggingAnimation(_:)` modifier to select an animation to use while dragging
- Convenience builder methods `none` and `interactiveSpring` to create `DraggingAnimation`

### Deprecations
- `rotation3D()` in favor of `interactive(rotation:)`
- `interactive(_:)` in favor of `interactive(scale:)`
- `pagingAnimation(_:)` in favor of `dragggingAnimation(_:)`

0 comments on commit 80a31d0

Please sign in to comment.