Animate dimming view opacity based on sheet height
This commit is contained in:
parent
9ddd39da4c
commit
08846bbc09
|
@ -18,6 +18,7 @@
|
|||
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 */; };
|
||||
D610D2FF23395975009EB06A /* Detent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D610D2FE23395975009EB06A /* Detent.swift */; };
|
||||
D6B61D63233A748300809DE7 /* MathHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B61D62233A748300809DE7 /* MathHelpers.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
@ -58,6 +59,7 @@
|
|||
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>"; };
|
||||
D610D2FE23395975009EB06A /* Detent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Detent.swift; sourceTree = "<group>"; };
|
||||
D6B61D62233A748300809DE7 /* MathHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MathHelpers.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
@ -102,6 +104,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
D610D2D4233945AF009EB06A /* SheetImagePicker.h */,
|
||||
D6B61D62233A748300809DE7 /* MathHelpers.swift */,
|
||||
D610D2FC23394E00009EB06A /* SheetContainerViewController.swift */,
|
||||
D610D2FE23395975009EB06A /* Detent.swift */,
|
||||
D610D2D5233945AF009EB06A /* Info.plist */,
|
||||
|
@ -246,6 +249,7 @@
|
|||
files = (
|
||||
D610D2FD23394E00009EB06A /* SheetContainerViewController.swift in Sources */,
|
||||
D610D2FF23395975009EB06A /* Detent.swift in Sources */,
|
||||
D6B61D63233A748300809DE7 /* MathHelpers.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// MathHelpers.swift
|
||||
// SheetImagePicker
|
||||
//
|
||||
// Created by Shadowfacts on 9/24/19.
|
||||
// Copyright © 2019 Shadowfacts. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
func clamp(_ value: CGFloat, from: CGFloat, to: CGFloat) -> CGFloat {
|
||||
if value < from {
|
||||
return from
|
||||
} else if value > to {
|
||||
return to
|
||||
} else {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
func smoothstep(value: CGFloat, from: CGFloat, to: CGFloat) -> CGFloat {
|
||||
let x = clamp((value - from) / (to - from), from: 0, to: 1)
|
||||
// 3x^2 - 2x^3
|
||||
return 3 * pow(x, 2) - 2 * pow(x, 3)
|
||||
}
|
||||
|
||||
func lerp(_ value: CGFloat, min: CGFloat, max: CGFloat, from: CGFloat, to: CGFloat) -> CGFloat {
|
||||
let value = clamp((value - min) / (max - min), from: 0, to: 1)
|
||||
return value * (to - from) + from
|
||||
}
|
|
@ -31,6 +31,9 @@ public class SheetContainerViewController: UIViewController {
|
|||
var topDetent: (detent: Detent, offset: CGFloat) {
|
||||
return detents.map { ($0, $0.offset(in: view)) }.min(by: { $0.1 < $1.1 })!
|
||||
}
|
||||
var bottomDetent: (detent: Detent, offset: CGFloat) {
|
||||
return detents.map { ($0, $0.offset(in: view)) }.max(by: { $0.1 < $1.1 })!
|
||||
}
|
||||
|
||||
public var minimumDetentJumpVelocity: CGFloat = 500
|
||||
public var maximumStretchDistance: CGFloat = 15
|
||||
|
@ -39,6 +42,8 @@ public class SheetContainerViewController: UIViewController {
|
|||
lazy var initialConstant: CGFloat = view.bounds.height / 2
|
||||
|
||||
var dimmingView: UIView!
|
||||
public var minimumDimmingAlpha: CGFloat = 0
|
||||
public var maximumDimmingAlpha: CGFloat = 0.75
|
||||
|
||||
public init(content: UIViewController) {
|
||||
self.content = content
|
||||
|
@ -56,7 +61,7 @@ public class SheetContainerViewController: UIViewController {
|
|||
dimmingView = UIView()
|
||||
dimmingView.translatesAutoresizingMaskIntoConstraints = false
|
||||
dimmingView.backgroundColor = .systemGray
|
||||
dimmingView.alpha = 0.5
|
||||
dimmingView.alpha = (maximumDimmingAlpha - minimumDimmingAlpha) / 2
|
||||
view.addSubview(dimmingView)
|
||||
NSLayoutConstraint.activate([
|
||||
dimmingView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||
|
@ -88,27 +93,14 @@ public class SheetContainerViewController: UIViewController {
|
|||
case .changed:
|
||||
let translation = recognizer.translation(in: content.view)
|
||||
var realOffset = initialConstant + translation.y
|
||||
if realOffset < topDetent.offset {
|
||||
func clamp(_ value: CGFloat, from: CGFloat, to: CGFloat) -> CGFloat {
|
||||
if value < from {
|
||||
return from
|
||||
} else if value > to {
|
||||
return to
|
||||
} else {
|
||||
return value
|
||||
}
|
||||
}
|
||||
func smoothstep(value: CGFloat, from: CGFloat, to: CGFloat) -> CGFloat {
|
||||
let x = clamp((value - from) / (to - from), from: 0, to: 1)
|
||||
// 3x^2 - 2x^3
|
||||
return 3 * pow(x, 2) - 2 * pow(x, 3)
|
||||
}
|
||||
let topOffset = topDetent.offset
|
||||
if realOffset < topOffset {
|
||||
let smoothed = smoothstep(value: realOffset, from: topOffset, to: 0)
|
||||
realOffset = topOffset - smoothed * maximumStretchDistance
|
||||
|
||||
}
|
||||
topConstraint.constant = realOffset
|
||||
dimmingView.alpha = lerp(realOffset, min: topOffset, max: bottomDetent.offset, from: maximumDimmingAlpha, to: minimumDimmingAlpha)
|
||||
|
||||
case .ended:
|
||||
let velocity = recognizer.velocity(in: view)
|
||||
|
@ -130,6 +122,7 @@ public class SheetContainerViewController: UIViewController {
|
|||
|
||||
UIView.animate(withDuration: 0.35, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: springVelocity, animations: {
|
||||
self.view.layoutIfNeeded()
|
||||
self.dimmingView.alpha = lerp(springToDetent.1, min: self.topDetent.offset, max: self.bottomDetent.offset, from: self.maximumDimmingAlpha, to: self.minimumDimmingAlpha)
|
||||
}, completion: { (finished) in
|
||||
self.delegate?.sheetContainer(self, didSnapToDetent: springToDetent.0)
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue