Skip to content

Commit

Permalink
II-15-[added animated finishing state to scroll view]
Browse files Browse the repository at this point in the history
  • Loading branch information
spopovshakuro committed Apr 28, 2024
1 parent 7dcca4e commit c4c0d18
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 12 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
![Shakuro PullToRefreshSwiftUI](Resources/title_image.png)
<br><br>
# PullToRefreshSwiftUI
![Version](https://img.shields.io/badge/version-1.3.1-blue.svg)
![Version](https://img.shields.io/badge/version-1.4.0-blue.svg)
![Platform](https://img.shields.io/badge/platform-iOS-lightgrey.svg)
![License MIT](https://img.shields.io/badge/license-MIT-green.svg)

Expand Down Expand Up @@ -131,7 +131,7 @@ Add `PullToRefreshSwiftUI` as a dependency in your `Package.swift` manifest:

```swift
dependencies: [
.package(url: "https://github.com/shakurocom/PullToRefreshSwiftUI.git", from: "1.3.1")
.package(url: "https://github.com/shakurocom/PullToRefreshSwiftUI.git", from: "1.4.0")
]
```

Expand Down
2 changes: 1 addition & 1 deletion Shakuro.PullToRefreshSwiftUI.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|

s.name = 'Shakuro.PullToRefreshSwiftUI'
s.version = '1.3.1'
s.version = '1.4.0'
s.summary = 'PullToRefreshSwiftUI'
s.homepage = 'https://github.com/shakurocom/PullToRefreshSwiftUI'
s.license = { :type => "MIT", :file => "LICENSE.md" }
Expand Down
1 change: 1 addition & 0 deletions Sources/PullToRefreshSwiftUI/PullToRefreshListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ public struct PullToRefreshListView<AnimationViewType: View, ContentViewType: Vi

private func resetReadyTriggeredStateIfNeeded() {
if scrollViewState.contentOffset <= 1 &&
scrollViewState.progress == 0 &&
scrollViewState.isTriggered &&
!scrollViewState.isRefreshing &&
!scrollViewState.isDragging {
Expand Down
33 changes: 24 additions & 9 deletions Sources/PullToRefreshSwiftUI/PullToRefreshScrollView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ public struct PullToRefreshScrollView<AnimationViewType: View, ContentViewType:
debugPrint("Current offset: \(offsetConclusive) = \(data.frameInCoordinateSpace.minY) - \(topOffset)")
scrollViewState.contentOffset = offsetConclusive
updateProgressIfNeeded()
stopIfNeeded()
resetReadyTriggeredStateIfNeeded()
startIfNeeded()
})
Expand All @@ -115,12 +114,12 @@ public struct PullToRefreshScrollView<AnimationViewType: View, ContentViewType:
.onChange(of: isRefreshing.wrappedValue, perform: { (isRefreshing) in
if !isRefreshing {
scrollViewState.isRefreshing = false
stopIfNeeded()
stopIfNeeded(animated: true)
resetReadyTriggeredStateIfNeeded()
}
})
.onChange(of: scrollViewState.isDragging, perform: { (_) in
stopIfNeeded()
stopIfNeeded(animated: false)
resetReadyTriggeredStateIfNeeded()
})
}
Expand All @@ -141,16 +140,32 @@ public struct PullToRefreshScrollView<AnimationViewType: View, ContentViewType:
}
}

private func stopIfNeeded() {
private func stopIfNeeded(animated: Bool) {
if !scrollViewState.isRefreshing && !scrollViewState.isDragging {
if scrollViewState.progress > 0 {
scrollViewState.progress = 0
if animated {
scrollViewState.isFinishing = true
Timer.scheduledTimer(withTimeInterval: 0.005, repeats: true, block: { (timer) in
let progressLocal = scrollViewState.progress - 0.03
if progressLocal <= 0 {
scrollViewState.isFinishing = false
scrollViewState.progress = 0
resetReadyTriggeredStateIfNeeded()
timer.invalidate()
} else {
scrollViewState.progress = progressLocal
}
})
} else {
scrollViewState.progress = 0
}
}
}
}

private func resetReadyTriggeredStateIfNeeded() {
if scrollViewState.contentOffset <= 1 &&
scrollViewState.progress == 0 &&
scrollViewState.isTriggered &&
!scrollViewState.isRefreshing &&
!scrollViewState.isDragging {
Expand All @@ -160,7 +175,7 @@ public struct PullToRefreshScrollView<AnimationViewType: View, ContentViewType:
}

private func updateProgressIfNeeded() {
if !scrollViewState.isRefreshing && !scrollViewState.isTriggered {
if !scrollViewState.isRefreshing && !scrollViewState.isTriggered && !scrollViewState.isFinishing {
// initial pulling will increase progress to 1; then when drag finished or
// fetch finished stopIfNeeded() will be called where progress will be set to 0.
// isRefreshing check is here because we need to remove conflict between setting progress.
Expand Down Expand Up @@ -215,6 +230,7 @@ private class ScrollViewState: NSObject, ObservableObject, UIGestureRecognizerDe
@Published var isDragging: Bool = false
@Published var isTriggered: Bool = false
@Published var isRefreshing: Bool = false
@Published var isFinishing: Bool = false
@Published var contentOffset: CGFloat = 0
@Published var progress: CGFloat = 0

Expand All @@ -225,10 +241,9 @@ private class ScrollViewState: NSObject, ObservableObject, UIGestureRecognizerDe
var state: PullToRefreshScrollViewState {
if isRefreshing {
return .refreshing
} else if progress > 0 && !isTriggered {
} else if progress > 0 && !isTriggered && !isFinishing {
return .pulling(progress: progress)
} else if contentOffset > 0 {
let progress = min(max((contentOffset * 2) / pullToRefreshAnimationHeight, 0), 1)
} else if isFinishing {
return .finishing(progress: progress, isTriggered: isTriggered)
} else {
return .idle
Expand Down

0 comments on commit c4c0d18

Please sign in to comment.