Add sheet presentation/dismissal animations
This commit is contained in:
parent
08846bbc09
commit
07a6ddf1b9
|
@ -18,6 +18,8 @@
|
||||||
D610D2F6233945C0009EB06A /* SheetImagePicker.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D610D2D1233945AF009EB06A /* SheetImagePicker.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
D610D2F6233945C0009EB06A /* SheetImagePicker.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D610D2D1233945AF009EB06A /* SheetImagePicker.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
D610D2FD23394E00009EB06A /* SheetContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D610D2FC23394E00009EB06A /* SheetContainerViewController.swift */; };
|
D610D2FD23394E00009EB06A /* SheetContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D610D2FC23394E00009EB06A /* SheetContainerViewController.swift */; };
|
||||||
D610D2FF23395975009EB06A /* Detent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D610D2FE23395975009EB06A /* Detent.swift */; };
|
D610D2FF23395975009EB06A /* Detent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D610D2FE23395975009EB06A /* Detent.swift */; };
|
||||||
|
D6708861233ABF9100315DA9 /* SheetContainerPresentationAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6708860233ABF9100315DA9 /* SheetContainerPresentationAnimationController.swift */; };
|
||||||
|
D6708863233AC8F600315DA9 /* SheetContainerDismissAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6708862233AC8F600315DA9 /* SheetContainerDismissAnimationController.swift */; };
|
||||||
D6B61D63233A748300809DE7 /* MathHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B61D62233A748300809DE7 /* MathHelpers.swift */; };
|
D6B61D63233A748300809DE7 /* MathHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B61D62233A748300809DE7 /* MathHelpers.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
@ -59,6 +61,8 @@
|
||||||
D610D2F0233945BB009EB06A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
D610D2F0233945BB009EB06A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
D610D2FC23394E00009EB06A /* SheetContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SheetContainerViewController.swift; sourceTree = "<group>"; };
|
D610D2FC23394E00009EB06A /* SheetContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SheetContainerViewController.swift; sourceTree = "<group>"; };
|
||||||
D610D2FE23395975009EB06A /* Detent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Detent.swift; sourceTree = "<group>"; };
|
D610D2FE23395975009EB06A /* Detent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Detent.swift; sourceTree = "<group>"; };
|
||||||
|
D6708860233ABF9100315DA9 /* SheetContainerPresentationAnimationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SheetContainerPresentationAnimationController.swift; sourceTree = "<group>"; };
|
||||||
|
D6708862233AC8F600315DA9 /* SheetContainerDismissAnimationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SheetContainerDismissAnimationController.swift; sourceTree = "<group>"; };
|
||||||
D6B61D62233A748300809DE7 /* MathHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MathHelpers.swift; sourceTree = "<group>"; };
|
D6B61D62233A748300809DE7 /* MathHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MathHelpers.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
@ -106,6 +110,8 @@
|
||||||
D610D2D4233945AF009EB06A /* SheetImagePicker.h */,
|
D610D2D4233945AF009EB06A /* SheetImagePicker.h */,
|
||||||
D6B61D62233A748300809DE7 /* MathHelpers.swift */,
|
D6B61D62233A748300809DE7 /* MathHelpers.swift */,
|
||||||
D610D2FC23394E00009EB06A /* SheetContainerViewController.swift */,
|
D610D2FC23394E00009EB06A /* SheetContainerViewController.swift */,
|
||||||
|
D6708860233ABF9100315DA9 /* SheetContainerPresentationAnimationController.swift */,
|
||||||
|
D6708862233AC8F600315DA9 /* SheetContainerDismissAnimationController.swift */,
|
||||||
D610D2FE23395975009EB06A /* Detent.swift */,
|
D610D2FE23395975009EB06A /* Detent.swift */,
|
||||||
D610D2D5233945AF009EB06A /* Info.plist */,
|
D610D2D5233945AF009EB06A /* Info.plist */,
|
||||||
);
|
);
|
||||||
|
@ -249,6 +255,8 @@
|
||||||
files = (
|
files = (
|
||||||
D610D2FD23394E00009EB06A /* SheetContainerViewController.swift in Sources */,
|
D610D2FD23394E00009EB06A /* SheetContainerViewController.swift in Sources */,
|
||||||
D610D2FF23395975009EB06A /* Detent.swift in Sources */,
|
D610D2FF23395975009EB06A /* Detent.swift in Sources */,
|
||||||
|
D6708861233ABF9100315DA9 /* SheetContainerPresentationAnimationController.swift in Sources */,
|
||||||
|
D6708863233AC8F600315DA9 /* SheetContainerDismissAnimationController.swift in Sources */,
|
||||||
D6B61D63233A748300809DE7 /* MathHelpers.swift in Sources */,
|
D6B61D63233A748300809DE7 /* MathHelpers.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
//
|
||||||
|
// SheetContainerDismissAnimationController.swift
|
||||||
|
// SheetImagePicker
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 9/24/19.
|
||||||
|
// Copyright © 2019 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class SheetContainerDismissAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
|
||||||
|
|
||||||
|
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
|
||||||
|
return 0.35
|
||||||
|
}
|
||||||
|
|
||||||
|
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
|
||||||
|
guard let fromVC = transitionContext.viewController(forKey: .from) as? SheetContainerViewController else {
|
||||||
|
fatalError()
|
||||||
|
}
|
||||||
|
|
||||||
|
fromVC.view.alpha = 1.0
|
||||||
|
fromVC.dimmingView.isHidden = true
|
||||||
|
|
||||||
|
let dimmingView = UIView(frame: fromVC.view.frame)
|
||||||
|
dimmingView.backgroundColor = .systemGray
|
||||||
|
dimmingView.alpha = fromVC.dimmingView.alpha
|
||||||
|
|
||||||
|
let container = transitionContext.containerView
|
||||||
|
container.addSubview(dimmingView)
|
||||||
|
container.addSubview(fromVC.view)
|
||||||
|
|
||||||
|
let duration = transitionDuration(using: transitionContext)
|
||||||
|
UIView.animate(withDuration: duration, animations: {
|
||||||
|
dimmingView.alpha = 0
|
||||||
|
fromVC.view.transform = CGAffineTransform(translationX: 0, y: fromVC.view.bounds.height)
|
||||||
|
}, completion: { (finished) in
|
||||||
|
dimmingView.removeFromSuperview()
|
||||||
|
|
||||||
|
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
//
|
||||||
|
// SheetContainerPresentationAnimationController.swift
|
||||||
|
// SheetImagePicker
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 9/24/19.
|
||||||
|
// Copyright © 2019 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class SheetContainerPresentationAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
|
||||||
|
|
||||||
|
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
|
||||||
|
return 0.35
|
||||||
|
}
|
||||||
|
|
||||||
|
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
|
||||||
|
guard let toVC = transitionContext.viewController(forKey: .to) as? SheetContainerViewController else {
|
||||||
|
fatalError()
|
||||||
|
}
|
||||||
|
|
||||||
|
toVC.dimmingView.isHidden = true
|
||||||
|
|
||||||
|
let finalFrame = transitionContext.finalFrame(for: toVC)
|
||||||
|
|
||||||
|
let dimmingView = UIView(frame: finalFrame)
|
||||||
|
dimmingView.backgroundColor = .systemGray
|
||||||
|
dimmingView.alpha = 0
|
||||||
|
|
||||||
|
let container = transitionContext.containerView
|
||||||
|
container.addSubview(dimmingView)
|
||||||
|
container.addSubview(toVC.view)
|
||||||
|
|
||||||
|
toVC.view.transform = CGAffineTransform(translationX: 0, y: toVC.view.bounds.height)
|
||||||
|
|
||||||
|
let duration = transitionDuration(using: transitionContext)
|
||||||
|
UIView.animate(withDuration: duration, animations: {
|
||||||
|
dimmingView.alpha = toVC.dimmingView.alpha
|
||||||
|
toVC.view.transform = .identity
|
||||||
|
}, completion: { (finished) in
|
||||||
|
dimmingView.removeFromSuperview()
|
||||||
|
toVC.dimmingView.isHidden = false
|
||||||
|
|
||||||
|
toVC.view.frame = finalFrame
|
||||||
|
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -49,6 +49,9 @@ public class SheetContainerViewController: UIViewController {
|
||||||
self.content = content
|
self.content = content
|
||||||
|
|
||||||
super.init(nibName: nil, bundle: nil)
|
super.init(nibName: nil, bundle: nil)
|
||||||
|
|
||||||
|
modalPresentationStyle = .custom
|
||||||
|
transitioningDelegate = self
|
||||||
}
|
}
|
||||||
|
|
||||||
required public init?(coder: NSCoder) {
|
required public init?(coder: NSCoder) {
|
||||||
|
@ -151,3 +154,11 @@ public class SheetContainerViewController: UIViewController {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension SheetContainerViewController: UIViewControllerTransitioningDelegate {
|
||||||
|
public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||||||
|
return SheetContainerPresentationAnimationController()
|
||||||
|
}
|
||||||
|
public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||||||
|
return SheetContainerDismissAnimationController()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15400" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||||
|
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15404"/>
|
||||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@ -9,16 +10,30 @@
|
||||||
<!--View Controller-->
|
<!--View Controller-->
|
||||||
<scene sceneID="tne-QT-ifu">
|
<scene sceneID="tne-QT-ifu">
|
||||||
<objects>
|
<objects>
|
||||||
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
|
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="SheetImagePickerTest" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
<subviews>
|
||||||
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tfd-T0-fMO">
|
||||||
|
<rect key="frame" x="184" y="433" width="46" height="30"/>
|
||||||
|
<state key="normal" title="Button"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="buttonPressed:" destination="BYZ-38-t0r" eventType="touchUpInside" id="tmi-VL-j61"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="tfd-T0-fMO" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="Cpn-cM-hYr"/>
|
||||||
|
<constraint firstItem="tfd-T0-fMO" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="YJH-oX-yBz"/>
|
||||||
|
</constraints>
|
||||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||||
</view>
|
</view>
|
||||||
</viewController>
|
</viewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||||
</objects>
|
</objects>
|
||||||
|
<point key="canvasLocation" x="139" y="138"/>
|
||||||
</scene>
|
</scene>
|
||||||
</scenes>
|
</scenes>
|
||||||
</document>
|
</document>
|
||||||
|
|
|
@ -15,38 +15,25 @@ class ViewController: UIViewController {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
// Do any additional setup after loading the view.
|
// Do any additional setup after loading the view.
|
||||||
view.backgroundColor = .green
|
view.backgroundColor = .green
|
||||||
|
}
|
||||||
|
|
||||||
|
@IBAction func buttonPressed(_ sender: Any) {
|
||||||
let content = UIViewController()
|
let content = UIViewController()
|
||||||
content.view.translatesAutoresizingMaskIntoConstraints = false
|
content.view.translatesAutoresizingMaskIntoConstraints = false
|
||||||
content.view.backgroundColor = .red
|
content.view.backgroundColor = .red
|
||||||
let sheet = SheetContainerViewController(content: content)
|
let sheet = SheetContainerViewController(content: content)
|
||||||
sheet.delegate = self
|
sheet.delegate = self
|
||||||
sheet.detents = [.bottom, .middle, .top]
|
sheet.detents = [.bottom, .middle, .top]
|
||||||
// sheet.view.backgroundColor = .blue
|
|
||||||
|
|
||||||
addChild(sheet)
|
present(sheet, animated: true)
|
||||||
sheet.didMove(toParent: self)
|
|
||||||
view.addSubview(sheet.view)
|
|
||||||
NSLayoutConstraint.activate([
|
|
||||||
sheet.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
|
||||||
sheet.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
|
||||||
sheet.view.topAnchor.constraint(equalTo: view.topAnchor),
|
|
||||||
sheet.view.bottomAnchor.constraint(equalTo: view.bottomAnchor)
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ViewController: SheetContainerViewControllerDelegate {
|
extension ViewController: SheetContainerViewControllerDelegate {
|
||||||
func sheetContainer(_ sheetContainer: SheetContainerViewController, willSnapToDetent detent: Detent) -> Bool {
|
func sheetContainer(_ sheetContainer: SheetContainerViewController, willSnapToDetent detent: Detent) -> Bool {
|
||||||
if detent == .bottom {
|
if detent == .bottom {
|
||||||
UIView.animate(withDuration: 0.35, animations: {
|
sheetContainer.dismiss(animated: true)
|
||||||
sheetContainer.view.transform = CGAffineTransform(translationX: 0, y: sheetContainer.view.bounds.height)
|
|
||||||
}, completion: { (finished) in
|
|
||||||
sheetContainer.removeFromParent()
|
|
||||||
sheetContainer.didMove(toParent: nil)
|
|
||||||
sheetContainer.view.removeFromSuperview()
|
|
||||||
})
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
Loading…
Reference in New Issue