diff --git a/experiments/swift-programmatic-modal/Test/RoundedViewTestViewController.swift b/experiments/swift-programmatic-modal/Test/RoundedViewTestViewController.swift new file mode 100644 index 00000000..47305970 --- /dev/null +++ b/experiments/swift-programmatic-modal/Test/RoundedViewTestViewController.swift @@ -0,0 +1,145 @@ +// +// RoundedViewTestViewController.swift +// swift-programmatic-modal +// +// Created by Dominic Go on 6/4/23. +// + +import UIKit + +class RoundedView: UIView { + override init(frame: CGRect) { + super.init(frame: frame); + + let bounds = CGRect( + origin: .zero, + size: frame.size + ); + + self.layer.mask = self.makeShapeMask(bounds: bounds); + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + }; + + override func layoutSubviews() { + super.layoutSubviews(); + + self.layer.mask = self.makeShapeMask(bounds: self.bounds); + }; + + func makeShapeMask(bounds: CGRect) -> CAShapeLayer { + let path = UIBezierPath( + shouldRoundRect: bounds, + topLeftRadius: 30, + topRightRadius: 30, + bottomLeftRadius: 30, + bottomRightRadius: 30 + ); + + let shape = CAShapeLayer(); + shape.path = path.cgPath; + + return shape; + }; +}; + +class RoundedViewTestViewController: UIViewController { + + lazy var roundedView: RoundedView = { + let view = RoundedView(frame: CGRect( + origin: .zero, + size: CGSize(width: 150, height: 150) + ) + ); + + view.backgroundColor = .red; + + return view; + }(); + + override func viewDidLoad() { + self.view.backgroundColor = .systemBackground; + + let roundedView = self.roundedView; + roundedView.center = self.view.center; + roundedView.frame = roundedView.frame.offsetBy(dx: 0, dy: -200) + + self.view.addSubview(roundedView); + + let prevFrame = roundedView.frame; + let prevBounds = roundedView.bounds; + + var nextFrame = roundedView.frame.offsetBy(dx: 0, dy: 300); + nextFrame.size = CGSize( + width: nextFrame.width + 100, + height: nextFrame.height + 100 + ); + + let nextBounds = CGRect( + origin: .zero, + size: nextFrame.size + ); + + let prevMask: CAShapeLayer = { + let path = UIBezierPath( + shouldRoundRect: prevBounds, + topLeftRadius: 10, + topRightRadius: 10, + bottomLeftRadius: 10, + bottomRightRadius: 10 + ); + + let shape = CAShapeLayer(); + shape.path = path.cgPath; + + return shape; + }(); + + let nextMask: CAShapeLayer = { + let path = UIBezierPath( + shouldRoundRect: nextBounds, + topLeftRadius: 30, + topRightRadius: 30, + bottomLeftRadius: 30, + bottomRightRadius: 30 + ); + + let shape = CAShapeLayer(); + shape.path = path.cgPath; + + return shape; + }(); + + let viewAnimator = UIViewPropertyAnimator( + duration: 4, + curve: .easeInOut + ); + + roundedView.translatesAutoresizingMaskIntoConstraints = false; + + viewAnimator.addAnimations { + UIView.addKeyframe( + withRelativeStartTime: 0, + relativeDuration: 0 + ) { + roundedView.frame = prevFrame; + roundedView.setNeedsLayout(); + roundedView.layoutIfNeeded(); + }; + + UIView.addKeyframe( + withRelativeStartTime: 1, + relativeDuration: 0 + ) { + roundedView.frame = nextFrame; + roundedView.setNeedsLayout(); + roundedView.layoutIfNeeded(); + }; + }; + + viewAnimator.startAnimation(); + }; +}; + diff --git a/experiments/swift-programmatic-modal/Test/TestRoutes.swift b/experiments/swift-programmatic-modal/Test/TestRoutes.swift index 359efabd..b0ea42df 100644 --- a/experiments/swift-programmatic-modal/Test/TestRoutes.swift +++ b/experiments/swift-programmatic-modal/Test/TestRoutes.swift @@ -13,6 +13,7 @@ enum TestRoutes { case RNILayoutTest; case RNIDraggableTest; case BlurEffectTest; + case RoundedViewTest; var viewController: UIViewController { switch self { @@ -24,6 +25,9 @@ enum TestRoutes { case .BlurEffectTest: return BlurEffectTestViewController(); + + case .RoundedViewTest: + return RoundedViewTestViewController(); }; }; }; 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 b28f7012..ff3c3fc5 100644 --- a/experiments/swift-programmatic-modal/swift-programmatic-modal.xcodeproj/project.pbxproj +++ b/experiments/swift-programmatic-modal/swift-programmatic-modal.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 88B7D0FB29C593F600490628 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 88B7D0F929C593F600490628 /* LaunchScreen.storyboard */; }; 88C2F45C2A275B2800DA7450 /* AdaptiveModalSnapPointPreset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88C2F45B2A275B2800DA7450 /* AdaptiveModalSnapPointPreset.swift */; }; 88C2F45E2A278A9200DA7450 /* AdaptiveModalPropertyAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88C2F45D2A278A9200DA7450 /* AdaptiveModalPropertyAnimator.swift */; }; + 88C2F4602A2CA8CF00DA7450 /* RoundedViewTestViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88C2F45F2A2CA8CF00DA7450 /* RoundedViewTestViewController.swift */; }; 88D016602A14C86B004664D2 /* RootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88D0165F2A14C86B004664D2 /* RootViewController.swift */; }; 88D0168D2A1730B1004664D2 /* RNILayoutTestViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88D0168C2A1730B1004664D2 /* RNILayoutTestViewController.swift */; }; 88D0169E2A1B0DD3004664D2 /* RNIDraggableTestViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88D0169D2A1B0DD3004664D2 /* RNIDraggableTestViewController.swift */; }; @@ -103,6 +104,7 @@ 88B7D0FC29C593F600490628 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 88C2F45B2A275B2800DA7450 /* AdaptiveModalSnapPointPreset.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdaptiveModalSnapPointPreset.swift; sourceTree = ""; }; 88C2F45D2A278A9200DA7450 /* AdaptiveModalPropertyAnimator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdaptiveModalPropertyAnimator.swift; sourceTree = ""; }; + 88C2F45F2A2CA8CF00DA7450 /* RoundedViewTestViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedViewTestViewController.swift; sourceTree = ""; }; 88D0165F2A14C86B004664D2 /* RootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootViewController.swift; sourceTree = ""; }; 88D0168C2A1730B1004664D2 /* RNILayoutTestViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNILayoutTestViewController.swift; sourceTree = ""; }; 88D0169D2A1B0DD3004664D2 /* RNIDraggableTestViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNIDraggableTestViewController.swift; sourceTree = ""; }; @@ -239,6 +241,7 @@ 88D0169D2A1B0DD3004664D2 /* RNIDraggableTestViewController.swift */, 88D0187B2A1B32E6004664D2 /* TestRoutes.swift */, 88D0187D2A1B6CB3004664D2 /* BlurEffectTestViewController.swift */, + 88C2F45F2A2CA8CF00DA7450 /* RoundedViewTestViewController.swift */, ); path = Test; sourceTree = ""; @@ -632,6 +635,7 @@ 88D018772A1B3030004664D2 /* RNIComputableValue.swift in Sources */, 88C2F45C2A275B2800DA7450 /* AdaptiveModalSnapPointPreset.swift in Sources */, 88E8C01C2A23203E008C2FF8 /* RNILayoutPreset.swift in Sources */, + 88C2F4602A2CA8CF00DA7450 /* RoundedViewTestViewController.swift in Sources */, 88D018292A1B3030004664D2 /* RNICleanupMode.swift in Sources */, 88D018532A1B3030004664D2 /* RNIMulticastDelegate.swift in Sources */, 88D018642A1B3030004664D2 /* RNIViewControllerLifeCycleNotifiable.swift in Sources */,