Skip to content

Commit

Permalink
draggingAnimation modifier
Browse files Browse the repository at this point in the history
Deprecating pagingAnimation. New modifier will be used onChanged and onEnded
  • Loading branch information
fermoya committed Apr 14, 2021
1 parent 55e5095 commit 4d723f7
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 12 deletions.
14 changes: 4 additions & 10 deletions Documentation/Usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,21 +227,15 @@ Transform your `Pager` into an endless sroll by using `loopPages`:

## Page Transitions

Use `pagingAnimation` to customize the _transition_ to the next page once the drag has ended. This is achieve by a block with a `DragResult`which contains:
* Current page
* Next page
* Total shift
* Velocity

By default, `pagingAnimation`is set to `standard`(a.k.a, `.easeOut`) for `singlePagination`and `steep`([custom bezier curve](https://cubic-bezier.com/#.2,1,.9,1)) for `multiplePagination`. If you wish to change the animation, you could do it as follows:
Use `draggingAnimation(_:)` to customize the _transition_ to the next page.

```swift
Pager(...)
.pagingAnimation({ currentPage, nextPage, totalShift, velocity in
return PagingAnimation.custom(animation: .easeInOut)
})
.draggingAnimation(.interactive)
```

By default, `draggingAnimation` is set to `.easeOut`.

## Events

Use `onPageWillChange` or `onPageChanged` to react to changes on the page index:
Expand Down
8 changes: 8 additions & 0 deletions Sources/SwiftUIPager/PageConfiguration/PagingAnimation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

import SwiftUI

@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
public typealias DraggingAnimation = PagingAnimation

/// Animation to be used when the user stops dragging
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
public enum PagingAnimation: Equatable {
Expand All @@ -24,6 +27,9 @@ public enum PagingAnimation: Equatable {
/// - Parameter duration: duration of the animation
case standard(duration: TimeInterval)

/// Interactive spring with a response of 0.3, dampingFraction: 0.8, and blendDuration: 0.5
case interactive

/// Pass your custom animation
///
/// - Parameter animation: animation to be applied
Expand All @@ -43,6 +49,8 @@ public enum PagingAnimation: Equatable {
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)
case .custom(let animation):
return animation
}
Expand Down
8 changes: 8 additions & 0 deletions Sources/SwiftUIPager/Pager+Buildable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ extension Pager: Buildable {
/// Sets the animation to be applied when the user stops dragging
///
/// - Parameter value: callback to get an animation based on the result of dragging
@available(*, deprecated, message: "This method will no longer be mantained in future versions. Please use `draggingAnimation(_:)` instead")
public func pagingAnimation(_ value: ((DragResult) -> PagingAnimation)?) -> Self {
mutating(keyPath: \.pagingAnimation, value: value)
}
Expand Down Expand Up @@ -69,6 +70,13 @@ extension Pager: Buildable {

#if !os(tvOS)

/// Sets the explicit animation used for dragging
///
/// - Parameter value: explicit animation
public func draggingAnimation(_ value: DraggingAnimation?) -> Self {
mutating(keyPath: \.draggingAnimation, value: value)
}

/// Sensitivity used to determine whether or not to swipe the page
///
/// - Parameter value: sensitivity to be applied when paginating
Expand Down
4 changes: 4 additions & 0 deletions Sources/SwiftUIPager/Pager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ public struct Pager<Element, ID, PageView>: View where PageView: View, Element:
/// Animation to be applied when the user stops dragging
var pagingAnimation: ((DragResult) -> PagingAnimation)?

/// Animation used for dragging
var draggingAnimation: DraggingAnimation?

/// Sensitivity used to determine whether or not to swipe the page
var sensitivity: PaginationSensitivity = .default

Expand Down Expand Up @@ -211,6 +214,7 @@ public struct Pager<Element, ID, PageView>: View where PageView: View, Element:
.onDraggingChanged(onDraggingChanged)
.onDraggingEnded(onDraggingEnded)
.bounces(bounces)
.draggingAnimation(draggingAnimation)
#endif

pagerContent = allowsMultiplePagination ? pagerContent.multiplePagination() : pagerContent
Expand Down
7 changes: 7 additions & 0 deletions Sources/SwiftUIPager/PagerContent+Buildable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ extension Pager.PagerContent: Buildable {

#if !os(tvOS)

/// Sets the explicit animation used for dragging
///
/// - Parameter value: explicit animation
func draggingAnimation(_ value: DraggingAnimation?) -> Self {
mutating(keyPath: \.draggingAnimation, value: value)
}

/// Sensitivity used to determine whether or not to swipe the page
///
/// - Parameter value: sensitivity to be applied when paginating
Expand Down
8 changes: 6 additions & 2 deletions Sources/SwiftUIPager/PagerContent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ extension Pager {
/// Animation to be applied when the user stops dragging
var pagingAnimation: ((DragResult) -> PagingAnimation)?

/// Animation used for dragging
var draggingAnimation: DraggingAnimation?

/// Sensitivity used to determine whether or not to swipe the page
var sensitivity: PaginationSensitivity = .default

Expand Down Expand Up @@ -222,7 +225,8 @@ extension Pager.PagerContent {
}

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

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

let animation = pagingAnimation.animation.speed(speed)
if page != newPage {
Expand Down
10 changes: 10 additions & 0 deletions Tests/SwiftUIPagerTests/Pager+Buildable_Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ final class Pager_Buildable_Tests: XCTestCase {
XCTAssertEqual(pager.contentLoadingPolicy, .default)
XCTAssertEqual(pager.allowsMultiplePagination, false)
XCTAssertNil(pager.pagingAnimation)
XCTAssertNil(pager.draggingAnimation)
XCTAssertEqual(pager.sensitivity, .default)
XCTAssertEqual(pager.pageRatio, 1)
XCTAssertTrue(pager.bounces)
Expand Down Expand Up @@ -113,6 +114,14 @@ final class Pager_Buildable_Tests: XCTestCase {
XCTAssertEqual(pagingAnimation, PagingAnimation.steep)
}

func test_GivenPager_WhenDraggingAnimation_ThenDraggingAnimationNotNil() throws {
var pager = givenPager
pager = pager.draggingAnimation(.steep)
let pagerContent = pager.content(for: CGSize(width: 100, height: 100))
let animation = try XCTUnwrap(pagerContent.draggingAnimation)
XCTAssertEqual(animation, PagingAnimation.steep)
}

func test_GivenPager_WhenMultiplePagination_ThenAllowsMultiplePagination() {
var pager = givenPager
pager = pager.multiplePagination()
Expand Down Expand Up @@ -608,6 +617,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_ThenDraggingAnimationNotNil", test_GivenPager_WhenDraggingAnimation_ThenDraggingAnimationNotNil),
("test_GivenPager_WhenHorizontalRightToLeft_ThenScrollAngle", test_GivenPager_WhenHorizontalRightToLeft_ThenScrollAngle),
("test_GivenPager_WhenAlignment_ThenAlignmentSet", test_GivenPager_WhenAlignment_ThenAlignmentSet),
("test_GivenPager_WhenVerticalBottomToTop_ThenScrollAngle", test_GivenPager_WhenVerticalBottomToTop_ThenScrollAngle),
Expand Down
7 changes: 7 additions & 0 deletions Tests/SwiftUIPagerTests/PagingAnimation_Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ final class PagingAnimation_Tests: XCTestCase {
XCTAssertEqual(animation, input)
}

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

static var allTests = [
("test_GivenPagingAnimationSteep_WhenAnimation_ThenExpectedAnimationValues", test_GivenPagingAnimationSteep_WhenAnimation_ThenExpectedAnimationValues),
("test_GivenPagingAnimationStandard_WhenAnimation_ThenExpectedAnimationValues", test_GivenPagingAnimationStandard_WhenAnimation_ThenExpectedAnimationValues),
Expand Down

0 comments on commit 4d723f7

Please sign in to comment.