Skip to content
Snippets Groups Projects
Commit 4249191b authored by Bruno Muniz's avatar Bruno Muniz :apple:
Browse files

Fixes scrolling of nickname drawer

parent a25859e9
No related branches found
No related tags found
1 merge request!100Fixes scrolling of nickname drawer
......@@ -226,6 +226,10 @@ let package = Package(
name: "XXModels",
package: "client-ios-db"
),
.product(
name: "ScrollViewController",
package: "ScrollViewController"
),
.product(
name: "Dependencies",
package: "swift-composable-architecture"
......
import UIKit
import Combine
final class BottomTransition: NSObject, UIViewControllerAnimatedTransitioning {
enum Direction {
......@@ -9,11 +8,10 @@ final class BottomTransition: NSObject, UIViewControllerAnimatedTransitioning {
let isDismissableOnBackground: Bool
var direction: Direction = .present
private let onDismissal: (() -> Void)?
private let onDismissal: () -> Void
private weak var darkOverlayView: UIControl?
private weak var topConstraint: NSLayoutConstraint?
private weak var bottomConstraint: NSLayoutConstraint?
private var cancellables = Set<AnyCancellable>()
private var presentedConstraints: [NSLayoutConstraint] = []
private var dismissedConstraints: [NSLayoutConstraint] = []
......@@ -21,7 +19,7 @@ final class BottomTransition: NSObject, UIViewControllerAnimatedTransitioning {
init(
_ isDismissableOnBackground: Bool = true,
onDismissal: (() -> Void)?
onDismissal: @escaping () -> Void
) {
self.onDismissal = onDismissal
self.isDismissableOnBackground = isDismissableOnBackground
......@@ -123,7 +121,7 @@ final class BottomTransition: NSObject, UIViewControllerAnimatedTransitioning {
},
completion: { [weak self] _ in
context.completeTransition(true)
self?.onDismissal?()
self?.onDismissal()
}
)
}
......
......@@ -23,3 +23,26 @@ final class BottomTransitioningDelegate: NSObject, UIViewControllerTransitioning
return transition
}
}
final class FullscreenTransitioningDelegate: NSObject, UIViewControllerTransitioningDelegate {
private var transition: FullscreenTransition?
func animationController(
forPresented presented: UIViewController,
presenting: UIViewController,
source: UIViewController
) -> UIViewControllerAnimatedTransitioning? {
transition = FullscreenTransition { [weak self] in
guard let self else { return }
self.transition = nil
}
return transition
}
func animationController(
forDismissed dismissed: UIViewController
) -> UIViewControllerAnimatedTransitioning? {
transition?.direction = .dismiss
return transition
}
}
import UIKit
final class FullscreenTransition: NSObject, UIViewControllerAnimatedTransitioning {
enum Direction {
case present
case dismiss
}
var direction: Direction = .present
private let onDismissal: () -> Void
private weak var darkOverlayView: UIControl?
private weak var topConstraint: NSLayoutConstraint?
private weak var bottomConstraint: NSLayoutConstraint?
private var presentedConstraints: [NSLayoutConstraint] = []
private var dismissedConstraints: [NSLayoutConstraint] = []
private var presentingController: UIViewController?
init(onDismissal: @escaping () -> Void) {
self.onDismissal = onDismissal
super.init()
}
func transitionDuration(
using context: UIViewControllerContextTransitioning?
) -> TimeInterval { 0.5 }
func animateTransition(
using context: UIViewControllerContextTransitioning
) {
switch direction {
case .present:
present(using: context)
case .dismiss:
dismiss(using: context)
}
}
private func present(using context: UIViewControllerContextTransitioning) {
guard let presentingController = context.viewController(forKey: .from),
let presentedView = context.view(forKey: .to) else {
context.completeTransition(false)
return
}
let darkOverlayView = UIControl()
self.darkOverlayView = darkOverlayView
darkOverlayView.alpha = 0.0
darkOverlayView.backgroundColor = UIColor.black.withAlphaComponent(0.5)
context.containerView.addSubview(darkOverlayView)
darkOverlayView.frame = context.containerView.bounds
darkOverlayView.addTarget(self, action: #selector(didTapOverlay), for: .touchUpInside)
self.presentingController = presentingController
context.containerView.addSubview(presentedView)
presentedView.translatesAutoresizingMaskIntoConstraints = false
presentedConstraints = [
presentedView.topAnchor.constraint(equalTo: context.containerView.topAnchor),
presentedView.leftAnchor.constraint(equalTo: context.containerView.leftAnchor),
presentedView.rightAnchor.constraint(equalTo: context.containerView.rightAnchor),
presentedView.bottomAnchor.constraint(equalTo: context.containerView.bottomAnchor)
]
dismissedConstraints = [
presentedView.leftAnchor.constraint(equalTo: context.containerView.leftAnchor),
presentedView.rightAnchor.constraint(equalTo: context.containerView.rightAnchor),
presentedView.topAnchor.constraint(equalTo: context.containerView.bottomAnchor),
presentedView.heightAnchor.constraint(equalTo: context.containerView.heightAnchor)
]
NSLayoutConstraint.activate(dismissedConstraints)
context.containerView.setNeedsLayout()
context.containerView.layoutIfNeeded()
NSLayoutConstraint.deactivate(dismissedConstraints)
NSLayoutConstraint.activate(presentedConstraints)
UIView.animate(
withDuration: transitionDuration(using: context),
delay: 0,
usingSpringWithDamping: 1,
initialSpringVelocity: 0,
options: .curveEaseInOut,
animations: {
darkOverlayView.alpha = 1.0
context.containerView.setNeedsLayout()
context.containerView.layoutIfNeeded()
},
completion: { _ in
context.completeTransition(true)
})
}
private func dismiss(using context: UIViewControllerContextTransitioning) {
NSLayoutConstraint.deactivate(presentedConstraints)
NSLayoutConstraint.activate(dismissedConstraints)
UIView.animate(
withDuration: transitionDuration(using: context),
delay: 0,
usingSpringWithDamping: 1,
initialSpringVelocity: 0,
options: .curveEaseInOut,
animations: { [weak darkOverlayView] in
darkOverlayView?.alpha = 0.0
context.containerView.setNeedsLayout()
context.containerView.layoutIfNeeded()
},
completion: { [weak self] _ in
context.completeTransition(true)
self?.onDismissal()
})
}
@objc private func didTapOverlay() {
if let presentingController {
presentingController.dismiss(animated: true)
}
}
}
import UIKit
import ScrollViewController
/// Opens up `Nickname` on a given parent view controller
public struct PresentNickname: Action {
......@@ -35,27 +36,31 @@ public struct PresentNickname: Action {
/// Performs `PresentNickname` action
public struct PresentNicknameNavigator: TypedNavigator {
/// Custom transitioning delegate
let transitioningDelegate = BottomTransitioningDelegate()
let transitioningDelegate = FullscreenTransitioningDelegate()
/// View controller which should be opened up
var viewController: (String, @escaping (String) -> Void) -> UIViewController
/// - Parameters:
/// - viewController: view controller which should be presented
public init(_ viewController: @escaping (
String, @escaping (String) -> Void
) -> UIViewController
) {
public init(_ viewController: @escaping (String, @escaping (String) -> Void) -> UIViewController) {
self.viewController = viewController
}
public func perform(_ action: PresentNickname, completion: @escaping () -> Void) {
let scrollViewController = ScrollViewController()
let controller = viewController(action.prefilled, action.completion)
scrollViewController.addChild(controller)
scrollViewController.contentView = controller.view
scrollViewController.wrapperView.handlesTouchesOutsideContent = true
scrollViewController.wrapperView.alignContentToBottom = true
scrollViewController.scrollView.bounces = false
controller.didMove(toParent: scrollViewController)
controller.transitioningDelegate = transitioningDelegate
controller.modalPresentationStyle = .overFullScreen
scrollViewController.modalPresentationStyle = .overFullScreen
action.parent.present(
controller,
scrollViewController,
animated: action.animated,
completion: completion
)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment