From 9f44dd6105a95c1bf80f96594d9079da69b26831 Mon Sep 17 00:00:00 2001 From: Dominic Go <18517029+dominicstop@users.noreply.github.com> Date: Sat, 27 May 2023 22:30:31 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=92=AB=20Update:=20Exp=20-=20`AdaptiveMod?= =?UTF-8?q?al`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Update experiment/test - `swift-programmatic-modal/AdaptiveModal`. --- .../AdaptiveModal/AdaptiveModalConfig.swift | 32 ++++++++++---- .../AdaptiveModalManager+Helpers.swift | 7 +++- .../AdaptiveModal/AdaptiveModalManager.swift | 42 ++++++++++++------- .../AdaptiveModalSnapAnimationConfig.swift | 20 +++++++++ .../project.pbxproj | 4 ++ .../Extensions/FloatingPoint+Clamping.swift | 5 ++- 6 files changed, 84 insertions(+), 26 deletions(-) create mode 100644 experiments/swift-programmatic-modal/AdaptiveModal/AdaptiveModalSnapAnimationConfig.swift diff --git a/experiments/swift-programmatic-modal/AdaptiveModal/AdaptiveModalConfig.swift b/experiments/swift-programmatic-modal/AdaptiveModal/AdaptiveModalConfig.swift index 0e2f22e2..b92324f7 100644 --- a/experiments/swift-programmatic-modal/AdaptiveModal/AdaptiveModalConfig.swift +++ b/experiments/swift-programmatic-modal/AdaptiveModal/AdaptiveModalConfig.swift @@ -7,9 +7,6 @@ import UIKit -enum AdaptiveModalSnapAnimationConfig { - -}; struct AdaptiveModalConfig { enum Direction { @@ -17,18 +14,35 @@ struct AdaptiveModalConfig { case vertical; }; + // MARK: - Properties + // ------------------ + + let snapPoints: [AdaptiveModalSnapPointConfig]; let snapDirection: Direction; + private let _snapAnimationConfig: AdaptiveModalSnapAnimationConfig?; + // let entranceConfig: AdaptiveModalEntranceConfig; - let snapSwipeVelocityThreshold: CGFloat = 0; - // let snappingAnimationConfig enum + // let snapSwipeVelocityThreshold: CGFloat = 0; + + // MARK: - Computed Properties + // --------------------------- + + var snapAnimationConfig: AdaptiveModalSnapAnimationConfig { + self._snapAnimationConfig ?? .default; + }; + + // MARK: - Init + // ------------ init( snapPoints: [AdaptiveModalSnapPointConfig], - snapDirection: Direction + snapDirection: Direction, + snapAnimationConfig: AdaptiveModalSnapAnimationConfig? = nil ) { - self.snapPoints = snapPoints - self.snapDirection = snapDirection - } + self.snapPoints = snapPoints; + self.snapDirection = snapDirection; + self._snapAnimationConfig = snapAnimationConfig; + }; }; diff --git a/experiments/swift-programmatic-modal/AdaptiveModal/AdaptiveModalManager+Helpers.swift b/experiments/swift-programmatic-modal/AdaptiveModal/AdaptiveModalManager+Helpers.swift index c8235043..70f1414e 100644 --- a/experiments/swift-programmatic-modal/AdaptiveModal/AdaptiveModalManager+Helpers.swift +++ b/experiments/swift-programmatic-modal/AdaptiveModal/AdaptiveModalManager+Helpers.swift @@ -87,10 +87,13 @@ extension AdaptiveModalManager { initialVelocity: CGFloat, decelerationRate: CGFloat = UIScrollView.DecelerationRate.normal.rawValue ) -> CGFloat { - let pointPerSecond = initialVelocity / 1000.0; + let pointPerSecond = abs(initialVelocity) / 1000.0; let accelerationRate = 1 - decelerationRate; let displacement = (pointPerSecond * decelerationRate) / accelerationRate; - return position + displacement; + + return initialVelocity > 0 + ? position + displacement + : position - displacement; }; }; diff --git a/experiments/swift-programmatic-modal/AdaptiveModal/AdaptiveModalManager.swift b/experiments/swift-programmatic-modal/AdaptiveModal/AdaptiveModalManager.swift index d687f772..008b7f3b 100644 --- a/experiments/swift-programmatic-modal/AdaptiveModal/AdaptiveModalManager.swift +++ b/experiments/swift-programmatic-modal/AdaptiveModal/AdaptiveModalManager.swift @@ -69,9 +69,7 @@ class AdaptiveModalManager { var targetRectProvider: () -> CGRect; var currentSizeProvider: () -> CGSize; - - let maxGestureVelocity: CGFloat = 20; - + weak var targetView: UIView?; weak var modalView: UIView?; @@ -127,9 +125,11 @@ class AdaptiveModalManager { velocity = gestureVelocityCoord / distance; }; + let snapAnimationConfig = self.modalConfig.snapAnimationConfig; + velocity = velocity.clamped( - min: -self.maxGestureVelocity, - max: self.maxGestureVelocity + min: -snapAnimationConfig.maxGestureVelocity, + max: snapAnimationConfig.maxGestureVelocity ); return CGVector(dx: velocity, dy: velocity); @@ -199,16 +199,15 @@ class AdaptiveModalManager { let animator: UIViewPropertyAnimator = { if let gestureInitialVelocity = self.gestureInitialVelocity { + let snapAnimationConfig = self.modalConfig.snapAnimationConfig; + let springTiming = UISpringTimingParameters( - dampingRatio: 1, + dampingRatio: snapAnimationConfig.springDampingRatio, initialVelocity: gestureInitialVelocity ); - - // Move to animation config - let springAnimationSettlingTime: CGFloat = 0.4; - + return UIViewPropertyAnimator( - duration: springAnimationSettlingTime, + duration: snapAnimationConfig.springAnimationSettlingTime, timingParameters: springTiming ); }; @@ -234,12 +233,23 @@ class AdaptiveModalManager { computedRect: CGRect ) { let snapRects = self.computedSnapRects; - let gestureCoordAdj = gestureCoord + (self.gestureOffset ?? 0); + + let gestureOffset = self.gestureOffset ?? 0; + let gestureCoordAdj = gestureCoord - gestureOffset; let delta = snapRects.map { abs($0.origin[keyPath: self.inputAxisKey] - gestureCoordAdj); }; + print( + "snapRects: \(snapRects.map { $0.origin[keyPath: self.inputAxisKey] })" + + "\n - delta: \(delta)" + + "\n - gestureCoord: \(gestureCoord)" + + "\n - gestureOffset: \(gestureOffset)" + + "\n - gestureCoordAdj: \(gestureCoordAdj)" + + "\n" + ); + let deltaSorted = delta.enumerated().sorted { $0.element < $1.element }; @@ -344,8 +354,6 @@ class AdaptiveModalManager { let gestureVelocity = gesture.velocity(in: self.targetView); self.gestureVelocity = gestureVelocity; - let gestureVelocityCoord = gestureVelocity[keyPath: self.inputAxisKey]; - switch gesture.state { case .began: self.gestureInitialPoint = gesturePoint; @@ -358,6 +366,12 @@ class AdaptiveModalManager { forGestureCoord: gestureFinalPoint[keyPath: self.inputAxisKey] ); + print( + "closestSnapPoint: \(closestSnapPoint.computedRect)" + + "\n - gesturePoint: \(gesturePoint)" + + "\n - gestureFinalPoint: \(gestureFinalPoint)" + ); + self.animateModal(toRect: closestSnapPoint.computedRect); self.currentSnapPointIndex = closestSnapPoint.snapPointIndex; diff --git a/experiments/swift-programmatic-modal/AdaptiveModal/AdaptiveModalSnapAnimationConfig.swift b/experiments/swift-programmatic-modal/AdaptiveModal/AdaptiveModalSnapAnimationConfig.swift new file mode 100644 index 00000000..9ac97775 --- /dev/null +++ b/experiments/swift-programmatic-modal/AdaptiveModal/AdaptiveModalSnapAnimationConfig.swift @@ -0,0 +1,20 @@ +// +// AdaptiveModalSnapAnimationConfig.swift +// swift-programmatic-modal +// +// Created by Dominic Go on 5/27/23. +// + +import UIKit + +struct AdaptiveModalSnapAnimationConfig { + static let `default`: Self = .init( + springDampingRatio: 0.9, + springAnimationSettlingTime: 0.4, + maxGestureVelocity: 20 + ); + + let springDampingRatio: CGFloat; + let springAnimationSettlingTime: CGFloat; + let maxGestureVelocity: CGFloat; +}; diff --git a/experiments/swift-programmatic-modal/swift-programmatic-modal.xcodeproj/project.pbxproj b/experiments/swift-programmatic-modal/swift-programmatic-modal.xcodeproj/project.pbxproj index cb4b8790..8336fb4b 100644 --- a/experiments/swift-programmatic-modal/swift-programmatic-modal.xcodeproj/project.pbxproj +++ b/experiments/swift-programmatic-modal/swift-programmatic-modal.xcodeproj/project.pbxproj @@ -83,6 +83,7 @@ 88D0188A2A1DAEE6004664D2 /* AdaptiveModalSnapPointPreset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88D018892A1DAEE6004664D2 /* AdaptiveModalSnapPointPreset.swift */; }; 88D0188C2A1DB02E004664D2 /* AdaptiveModalEntranceConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88D0188B2A1DB02E004664D2 /* AdaptiveModalEntranceConfig.swift */; }; 88D0188E2A1DCA61004664D2 /* AdaptiveModalManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88D0188D2A1DCA61004664D2 /* AdaptiveModalManager.swift */; }; + 88E8C0182A224A8D008C2FF8 /* AdaptiveModalSnapAnimationConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88E8C0172A224A8D008C2FF8 /* AdaptiveModalSnapAnimationConfig.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -166,6 +167,7 @@ 88D018892A1DAEE6004664D2 /* AdaptiveModalSnapPointPreset.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdaptiveModalSnapPointPreset.swift; sourceTree = ""; }; 88D0188B2A1DB02E004664D2 /* AdaptiveModalEntranceConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdaptiveModalEntranceConfig.swift; sourceTree = ""; }; 88D0188D2A1DCA61004664D2 /* AdaptiveModalManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdaptiveModalManager.swift; sourceTree = ""; }; + 88E8C0172A224A8D008C2FF8 /* AdaptiveModalSnapAnimationConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdaptiveModalSnapAnimationConfig.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -502,6 +504,7 @@ 88D018872A1D0A36004664D2 /* AdaptiveModalConfig.swift */, 88D0188D2A1DCA61004664D2 /* AdaptiveModalManager.swift */, 88075E262A2121FE00B78388 /* AdaptiveModalManager+Helpers.swift */, + 88E8C0172A224A8D008C2FF8 /* AdaptiveModalSnapAnimationConfig.swift */, ); path = AdaptiveModal; sourceTree = ""; @@ -634,6 +637,7 @@ 88D0185B2A1B3030004664D2 /* RNIIdentifiable+Default.swift in Sources */, 88D018762A1B3030004664D2 /* RNIComputableSizeMode.swift in Sources */, 88D018262A1B3030004664D2 /* UIColor+Helpers.swift in Sources */, + 88E8C0182A224A8D008C2FF8 /* AdaptiveModalSnapAnimationConfig.swift in Sources */, 88D018562A1B3030004664D2 /* RNIWeakDictionary.swift in Sources */, 88203DC12A122AC20088C8E2 /* RNIDynamicModal.swift in Sources */, 88D018542A1B3030004664D2 /* RNIWeakArray.swift in Sources */, diff --git a/ios/src_library/Extensions/FloatingPoint+Clamping.swift b/ios/src_library/Extensions/FloatingPoint+Clamping.swift index 1c4f6422..c685ba9b 100644 --- a/ios/src_library/Extensions/FloatingPoint+Clamping.swift +++ b/ios/src_library/Extensions/FloatingPoint+Clamping.swift @@ -8,7 +8,10 @@ import UIKit extension FloatingPoint { - public func clamped(min lowerBound: Self?, max upperBound: Self?) -> Self { + public func clamped( + min lowerBound: Self? = nil, + max upperBound: Self? = nil + ) -> Self { var clampedValue = self; if let upperBound = upperBound {