Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions BottomPopup.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = MYV44LEMW9;
DEVELOPMENT_TEAM = UR2UCZHHPB;
INFOPLIST_FILE = BottomPopup/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = (
Expand All @@ -348,7 +348,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = MYV44LEMW9;
DEVELOPMENT_TEAM = UR2UCZHHPB;
INFOPLIST_FILE = BottomPopup/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = (
Expand Down
108 changes: 75 additions & 33 deletions BottomPopup/Base.lproj/Main.storyboard

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ final class BottomPopupDismissAnimator: NSObject, UIViewControllerAnimatedTransi

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let fromVC = transitionContext.viewController(forKey: .from)!
let dismissFrame = CGRect(origin: CGPoint(x: 0, y: UIScreen.main.bounds.size.height), size: fromVC.view.frame.size)
let x = attributesOwner.view.frame.origin.x
let dismissFrame = CGRect(origin: CGPoint(x: x, y: UIScreen.main.bounds.size.height), size: fromVC.view.frame.size)

UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
fromVC.view.frame = dismissFrame
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import UIKit

open class BottomPopupNavigationController: UINavigationController, BottomPopupAttributesDelegate {

private var transitionHandler: BottomPopupTransitionHandler?
open weak var popupDelegate: BottomPopupDelegate?

Expand All @@ -32,7 +33,12 @@ open class BottomPopupNavigationController: UINavigationController, BottomPopupA
popupDelegate?.bottomPopupViewLoaded()
self.view.accessibilityIdentifier = popupViewAccessibilityIdentifier
}


open override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
curveTopCorners()
}

override open func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)

Expand Down Expand Up @@ -76,13 +82,16 @@ open class BottomPopupNavigationController: UINavigationController, BottomPopupA

// MARK: - BottomPopupAttributesDelegate Variables
open var popupHeight: CGFloat { BottomPopupConstants.defaultHeight }
open var popupWidth: CGFloat { BottomPopupConstants.defaultWidth }
open var popupTopCornerRadius: CGFloat { BottomPopupConstants.defaultTopCornerRadius }
open var popupPresentDuration: Double { BottomPopupConstants.defaultPresentDuration }
open var popupDismissDuration: Double { BottomPopupConstants.defaultDismissDuration }
open var popupShouldDismissInteractivelty: Bool { BottomPopupConstants.dismissInteractively }
open var popupDimmingViewAlpha: CGFloat { BottomPopupConstants.dimmingViewDefaultAlphaValue }
open var popupShouldBeganDismiss: Bool { BottomPopupConstants.shouldBeganDismiss }
open var popupViewAccessibilityIdentifier: String { BottomPopupConstants.defaultPopupViewAccessibilityIdentifier }
open var popupShouldDismissOnTap: Bool { BottomPopupConstants.dismissOnTap }

}

extension BottomPopupNavigationController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ final class BottomPopupPresentAnimator: NSObject, UIViewControllerAnimatedTransi
let toVC = transitionContext.viewController(forKey: .to)!
transitionContext.containerView.addSubview(toVC.view)
let presentFrame = transitionContext.finalFrame(for: toVC)
let initialFrame = CGRect(origin: CGPoint(x: 0, y: UIScreen.main.bounds.size.height), size: presentFrame.size)
let initialFrame = CGRect(origin: CGPoint(x: presentFrame.origin.x, y: UIScreen.main.bounds.size.height), size: presentFrame.size)
toVC.view.frame = initialFrame
UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
toVC.view.frame = presentFrame
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ import UIKit
final class BottomPopupPresentationController: UIPresentationController {
private var dimmingView: UIView!
private var popupHeight: CGFloat
private var popupWidth: CGFloat
private unowned var attributesDelegate: BottomPopupAttributesDelegate

override var frameOfPresentedViewInContainerView: CGRect {
CGRect(origin: CGPoint(x: 0, y: UIScreen.main.bounds.size.height - popupHeight), size: CGSize(width: presentedViewController.view.frame.size.width, height: popupHeight))
let viewWidth = containerView?.frame.width ?? 0
let x = (viewWidth - popupWidth) / 2
return CGRect(origin: CGPoint(x: x, y: UIScreen.main.bounds.size.height - popupHeight), size: CGSize(width: popupWidth, height: popupHeight))
}

private func changeDimmingViewAlphaAlongWithAnimation(to alpha: CGFloat) {
Expand All @@ -31,16 +34,27 @@ final class BottomPopupPresentationController: UIPresentationController {
init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?, attributesDelegate: BottomPopupAttributesDelegate) {
self.attributesDelegate = attributesDelegate
popupHeight = attributesDelegate.popupHeight
popupWidth = attributesDelegate.popupWidth
super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
setupDimmingView()
}

override func containerViewWillLayoutSubviews() {
override func containerViewDidLayoutSubviews() {
dimmingView.frame = containerView?.bounds ?? .zero
presentedView?.frame = frameOfPresentedViewInContainerView
}

override func presentationTransitionWillBegin() {
containerView?.insertSubview(dimmingView, at: 0)
if let containerView {
dimmingView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
dimmingView.topAnchor.constraint(equalTo: containerView.topAnchor),
dimmingView.leftAnchor.constraint(equalTo: containerView.leftAnchor),
dimmingView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor),
dimmingView.rightAnchor.constraint(equalTo: containerView.rightAnchor),
])
}
changeDimmingViewAlphaAlongWithAnimation(to: attributesDelegate.popupDimmingViewAlpha)
}

Expand All @@ -57,11 +71,13 @@ final class BottomPopupPresentationController: UIPresentationController {

@objc private func handleTap(_ tap: UITapGestureRecognizer) {
guard attributesDelegate.popupShouldBeganDismiss else { return }
guard attributesDelegate.popupShouldDismissOnTap else { return }
presentedViewController.dismiss(animated: true, completion: nil)
}

@objc private func handleSwipe(_ swipe: UISwipeGestureRecognizer) {
guard attributesDelegate.popupShouldBeganDismiss else { return }
guard attributesDelegate.popupShouldDismissInteractivelty else { return }
presentedViewController.dismiss(animated: true, completion: nil)
}
}
Expand Down
4 changes: 4 additions & 0 deletions BottomPopup/BottomPopupController/BottomPopupUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,27 @@ public extension BottomPopupDelegate {

public protocol BottomPopupAttributesDelegate: class {
var popupHeight: CGFloat { get }
var popupWidth: CGFloat { get }
var popupTopCornerRadius: CGFloat { get }
var popupPresentDuration: Double { get }
var popupDismissDuration: Double { get }
var popupShouldDismissInteractivelty: Bool { get }
var popupDimmingViewAlpha: CGFloat { get }
var popupShouldBeganDismiss: Bool { get }
var popupViewAccessibilityIdentifier: String { get }
var popupShouldDismissOnTap: Bool { get }
}

public enum BottomPopupConstants {
static let minPercentOfVisiblePartToCompleteAnimation: CGFloat = 0.5
static let swipeDownThreshold: CGFloat = 1000
static let defaultHeight: CGFloat = 377.0
static let defaultWidth: CGFloat = 377.0
static let defaultTopCornerRadius: CGFloat = 10.0
static let defaultPresentDuration = 0.5
static let defaultDismissDuration = 0.5
static let dismissInteractively = true
static let dismissOnTap = true
static let shouldBeganDismiss = true
static let dimmingViewDefaultAlphaValue: CGFloat = 0.5
static let defaultPopupViewAccessibilityIdentifier: String = "bottomPopupView"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ open class BottomPopupViewController: UIViewController, BottomPopupAttributesDel
popupDelegate?.bottomPopupViewLoaded()
view.accessibilityIdentifier = popupViewAccessibilityIdentifier
}


open override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
curveTopCorners()
}

open override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
curveTopCorners()
Expand Down Expand Up @@ -74,11 +79,14 @@ open class BottomPopupViewController: UIViewController, BottomPopupAttributesDel

// MARK: - BottomPopupAttributesDelegate Variables
open var popupHeight: CGFloat { BottomPopupConstants.defaultHeight }
open var popupWidth: CGFloat { BottomPopupConstants.defaultWidth }
open var popupTopCornerRadius: CGFloat { BottomPopupConstants.defaultTopCornerRadius }
open var popupPresentDuration: Double { BottomPopupConstants.defaultPresentDuration }
open var popupDismissDuration: Double { BottomPopupConstants.defaultDismissDuration }
open var popupShouldDismissInteractivelty: Bool { BottomPopupConstants.dismissInteractively }
open var popupDimmingViewAlpha: CGFloat { BottomPopupConstants.dimmingViewDefaultAlphaValue }
open var popupShouldBeganDismiss: Bool { BottomPopupConstants.shouldBeganDismiss }
open var popupViewAccessibilityIdentifier: String { BottomPopupConstants.defaultPopupViewAccessibilityIdentifier }
open var popupShouldDismissOnTap: Bool { BottomPopupConstants.dismissOnTap }

}
4 changes: 4 additions & 0 deletions BottomPopup/ExampleNavigationController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class ExampleNavigationController: BottomPopupNavigationController {
var presentDuration: Double?
var dismissDuration: Double?
var shouldDismissInteractivelty: Bool?
var shouldBeganDismiss: Bool?
var shouldDismissOnTap: Bool?

// MARK: - BottomPopupAttributesDelegate Variables
override var popupHeight: CGFloat { height ?? 300.0 }
Expand All @@ -22,4 +24,6 @@ class ExampleNavigationController: BottomPopupNavigationController {
override var popupDismissDuration: Double { dismissDuration ?? 1.0 }
override var popupShouldDismissInteractivelty: Bool { shouldDismissInteractivelty ?? true }
override var popupDimmingViewAlpha: CGFloat { BottomPopupConstants.dimmingViewDefaultAlphaValue }
override var popupShouldBeganDismiss: Bool { shouldBeganDismiss ?? true }
override var popupShouldDismissOnTap: Bool { shouldDismissOnTap ?? true }
}
4 changes: 4 additions & 0 deletions BottomPopup/ExamplePopupViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class ExamplePopupViewController: BottomPopupViewController {
var presentDuration: Double?
var dismissDuration: Double?
var shouldDismissInteractivelty: Bool?
var shouldBeganDismiss: Bool?
var shouldDismissOnTap: Bool?

@IBAction func dismissButtonTapped(_ sender: UIButton) {
dismiss(animated: true, completion: nil)
Expand All @@ -26,4 +28,6 @@ class ExamplePopupViewController: BottomPopupViewController {
override var popupDismissDuration: Double { dismissDuration ?? 1.0 }
override var popupShouldDismissInteractivelty: Bool { shouldDismissInteractivelty ?? true }
override var popupDimmingViewAlpha: CGFloat { BottomPopupConstants.dimmingViewDefaultAlphaValue }
override var popupShouldBeganDismiss: Bool { shouldBeganDismiss ?? true }
override var popupShouldDismissOnTap: Bool { shouldDismissOnTap ?? true }
}
10 changes: 8 additions & 2 deletions BottomPopup/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class ViewController: UIViewController {
@IBOutlet weak var topCornerRadiusLabel: UILabel!
@IBOutlet weak var presentDurationLabel: UILabel!
@IBOutlet weak var dismissDurationLabel: UILabel!
@IBOutlet weak var shouldBeganDismissSwitch: UISwitch!
@IBOutlet weak var dismissOnTapSwitch: UISwitch!

var height: CGFloat = 300 {
didSet {
Expand All @@ -31,13 +33,13 @@ class ViewController: UIViewController {
}
}

var presentDuration: Double = 1.5 {
var presentDuration: Double = 0.5 {
didSet {
presentDurationLabel.text = String(format: "%.02f sec", presentDuration)
}
}

var dismissDuration: Double = 1.5 {
var dismissDuration: Double = 0.5 {
didSet {
dismissDurationLabel.text = String(format: "%.02f sec", dismissDuration)
}
Expand Down Expand Up @@ -83,6 +85,8 @@ class ViewController: UIViewController {
popupViewController.presentDuration = presentDuration
popupViewController.dismissDuration = dismissDuration
popupViewController.shouldDismissInteractivelty = dismissInteractivelySwitch.isOn
popupViewController.shouldBeganDismiss = shouldBeganDismissSwitch.isOn
popupViewController.shouldDismissOnTap = dismissOnTapSwitch.isOn
popupViewController.popupDelegate = self
present(popupViewController, animated: true, completion: nil)
}
Expand All @@ -94,6 +98,8 @@ class ViewController: UIViewController {
popupNavController.presentDuration = presentDuration
popupNavController.dismissDuration = dismissDuration
popupNavController.shouldDismissInteractivelty = dismissInteractivelySwitch.isOn
popupNavController.shouldBeganDismiss = shouldBeganDismissSwitch.isOn
popupNavController.shouldDismissOnTap = dismissOnTapSwitch.isOn
present(popupNavController, animated: true, completion: nil)
}
}
Expand Down