Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task/fix input accessory view #187

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
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
7 changes: 7 additions & 0 deletions .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions Derived/InfoPlists/PanModal-Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
2 changes: 1 addition & 1 deletion PanModal.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

Pod::Spec.new do |s|
s.name = 'PanModal'
s.version = '1.2.7'
s.version = '1.2.11'
s.summary = 'PanModal is an elegant and highly customizable presentation API for constructing bottom sheet modals on iOS.'

# This description is used to generate tags and improve search results.
Expand Down
738 changes: 738 additions & 0 deletions PanModal.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

143 changes: 143 additions & 0 deletions PanModal/Controller/PanModalNavigationController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
//
// PanModalNavigationController.swift
// PanModal
//
// Created by Semen Kologrivov on 07.07.2022.
//
import UIKit

open class PanModalNavController: UINavigationController, PanModalPresentable {

public var currentHeight: CGFloat = .zero
public var currentStateKeyboardIsShown = false

public var presentViewController: (UIViewController & PanModalPresentable) {
guard let viewControllers = self.viewControllers.last as? (UIViewController & PanModalPresentable) else {
fatalError("impl top controller PanModalPresentable")
}

return viewControllers
}

open func updatePanModal(toState state: PanModalPresentationController.PresentationState = .longForm) {
let inset = self.panScrollable?.contentInset ?? .zero

self.panModalSetNeedsLayoutUpdate()
self.panModalTransition(to: state)

self.panScrollable?.contentInset = inset
}

// MARK: - PanModalPresentable
open var panScrollable: UIScrollView? {
self.presentViewController.panScrollable
}

open var topOffset: CGFloat {
self.presentViewController.topOffset
}

open var longFormHeight: PanModalHeight {
guard let panScrollable = self.presentViewController as? PanModalKeyboardPresentable else {
return self.presentViewController.longFormHeight
}

let height = panScrollable.contentWithKeyboardHeight

if abs(height - self.currentHeight) < 5 {
return .contentHeight(self.currentHeight)
}

self.currentHeight = height

return .contentHeight(height)
}

open var cornerRadius: CGFloat {
self.presentViewController.cornerRadius
}

open var springDamping: CGFloat {
1
}

open var transitionDuration: Double {
self.presentViewController.transitionDuration
}

open var transitionAnimationOptions: UIView.AnimationOptions {
self.presentViewController.transitionAnimationOptions
}

open var panModalBackgroundColor: UIColor {
self.presentViewController.panModalBackgroundColor
}

open var dragIndicatorBackgroundColor: UIColor {
self.presentViewController.dragIndicatorBackgroundColor
}

open var scrollIndicatorInsets: UIEdgeInsets {
self.presentViewController.scrollIndicatorInsets
}

open var anchorModalToLongForm: Bool {
self.presentViewController.anchorModalToLongForm
}

open var allowsExtendedPanScrolling: Bool {
self.presentViewController.allowsExtendedPanScrolling
}

open var allowsDragToDismiss: Bool {
self.presentViewController.allowsDragToDismiss
}

open var allowsTapToDismiss: Bool {
self.presentViewController.allowsTapToDismiss
}

open var isUserInteractionEnabled: Bool {
self.presentViewController.isUserInteractionEnabled
}

open var isHapticFeedbackEnabled: Bool {
self.presentViewController.isHapticFeedbackEnabled
}

open var shouldRoundTopCorners: Bool {
self.presentViewController.shouldRoundTopCorners
}

open var showDragIndicator: Bool {
self.presentViewController.showDragIndicator
}

open func shouldRespond(to panModalGestureRecognizer: UIPanGestureRecognizer) -> Bool {
self.presentViewController.shouldRespond(to: panModalGestureRecognizer)
}

open func willRespond(to panModalGestureRecognizer: UIPanGestureRecognizer) {
self.presentViewController.willRespond(to: panModalGestureRecognizer)
}

open func shouldPrioritize(panModalGestureRecognizer: UIPanGestureRecognizer) -> Bool {
self.presentViewController.shouldPrioritize(panModalGestureRecognizer: panModalGestureRecognizer)
}

open func shouldTransition(to state: PanModalPresentationController.PresentationState) -> Bool {
self.presentViewController.shouldTransition(to: state)
}

open func willTransition(to state: PanModalPresentationController.PresentationState) {
self.presentViewController.willTransition(to: state)
}

open func panModalWillDismiss() {
self.presentViewController.panModalWillDismiss()
}

open func panModalDidDismiss() {
self.presentViewController.panModalDidDismiss()
}
}
50 changes: 45 additions & 5 deletions PanModal/Controller/PanModalPresentationController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ open class PanModalPresentationController: UIPresentationController {
*/
private var scrollViewYOffset: CGFloat = 0.0

private var scrollView: UIScrollView?

/**
An observer for the scroll view content offset
*/
Expand All @@ -84,6 +86,8 @@ open class PanModalPresentationController: UIPresentationController {
*/
private var longFormYPosition: CGFloat = 0

private var enableCustomInteractiveKeyboard: Bool = true

/**
Determine anchored Y postion based on the `anchorModalToLongForm` flag
*/
Expand Down Expand Up @@ -219,7 +223,7 @@ open class PanModalPresentationController: UIPresentationController {

override public func dismissalTransitionDidEnd(_ completed: Bool) {
if !completed { return }

presentable?.panModalDidDismiss()
}

Expand Down Expand Up @@ -303,7 +307,6 @@ public extension PanModalPresentationController {
configureViewLayout()
adjustPresentedViewFrame()
observe(scrollView: presentable?.panScrollable)
configureScrollViewInsets()
}

}
Expand Down Expand Up @@ -370,7 +373,7 @@ private extension PanModalPresentationController {
let adjustedSize = CGSize(width: frame.size.width, height: frame.size.height - anchoredYPosition)
let panFrame = panContainerView.frame
panContainerView.frame.size = frame.size

if ![shortFormYPosition, longFormYPosition].contains(panFrame.origin.y) {
// if the container is already in the correct position, no need to adjust positioning
// (rotations & size changes cause positioning to be out of sync)
Expand Down Expand Up @@ -429,6 +432,8 @@ private extension PanModalPresentationController {
longFormYPosition = layoutPresentable.longFormYPos
anchorModalToLongForm = layoutPresentable.anchorModalToLongForm
extendsPanScrolling = layoutPresentable.allowsExtendedPanScrolling
scrollView = layoutPresentable.panScrollable
enableCustomInteractiveKeyboard = layoutPresentable.enableCustomInteractiveKeyboard

containerView?.isUserInteractionEnabled = layoutPresentable.isUserInteractionEnabled
}
Expand Down Expand Up @@ -582,11 +587,41 @@ private extension PanModalPresentationController {
if presentedView.frame.origin.y < longFormYPosition {
yDisplacement /= 2.0
}

var contentOffset = scrollView?.contentOffset ?? .zero
adjust(toYPosition: presentedView.frame.origin.y + yDisplacement)

if enableCustomInteractiveKeyboard {
moveKeyboardView(displacement: yDisplacement)
}

panGestureRecognizer.setTranslation(.zero, in: presentedView)
}

func moveKeyboardView(displacement: CGFloat) {
let windows = UIApplication.shared.windows

if let keyboardWindow = windows
.first(where: { NSStringFromClass($0.classForCoder) == "UIRemoteKeyboardWindow" }) {

var frame = keyboardWindow.frame ?? .zero
frame.origin.y = max(displacement + frame.origin.y, .zero)

keyboardWindow.frame = frame ?? .zero

let accessoryView = windows
.first(where: { NSStringFromClass($0.classForCoder) == "UITextEffectsWindow" })

var accessoryFrame = accessoryView?.frame ?? .zero
accessoryFrame.origin.y = max(
displacement + (accessoryFrame.origin.y ?? .zero),
.zero
)

accessoryView?.frame = accessoryFrame ?? .zero
}
}

/**
Determines if we should fail the gesture recognizer based on certain conditions

Expand Down Expand Up @@ -643,6 +678,11 @@ private extension PanModalPresentationController {
PanModalAnimator.animate({ [weak self] in
self?.adjust(toYPosition: yPos)
self?.isPresentedViewAnimating = true

if self?.enableCustomInteractiveKeyboard ?? false {
self?.moveKeyboardView(displacement: -.greatestFiniteMagnitude)
}

}, config: presentable) { [weak self] didComplete in
self?.isPresentedViewAnimating = !didComplete
}
Expand All @@ -653,7 +693,7 @@ private extension PanModalPresentationController {
*/
func adjust(toYPosition yPos: CGFloat) {
presentedView.frame.origin.y = max(yPos, anchoredYPosition)

guard presentedView.frame.origin.y > shortFormYPosition else {
backgroundView.dimState = .max
return
Expand Down Expand Up @@ -828,7 +868,7 @@ extension PanModalPresentationController: UIGestureRecognizerDelegate {
is the pan scrollable view
*/
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return otherGestureRecognizer.view == presentable?.panScrollable
return true//otherGestureRecognizer.view == presentable?.panScrollable
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// PanModalKeyboardPresentable+Defaults.swift
// PanModal
//
// Created by Semen Kologrivov on 07.07.2022.
//

import UIKit

public extension PanModalKeyboardPresentable where Self: UIViewController {

var extrasHeight: CGFloat {
.zero
}

var minimumHeight: CGFloat {
.zero
}

var keyboardScrollView: UIScrollView? {
self.panScrollable
}

var contentWithKeyboardHeight: CGFloat {
let height = (self.keyboardScrollView?.contentSize.height ?? .zero) +
(self.titleView?.frame.height ?? .zero) +
self.keyboardHeight +
self.extrasHeight
return max(height, self.minimumHeight)
}
}
20 changes: 20 additions & 0 deletions PanModal/KeyboardPresentable/PanModalKeyboardPresentable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// PanModalKeyboardPresentable.swift
// PanModal
//
// Created by Semen Kologrivov on 07.07.2022.
//

import UIKit

public protocol PanModalKeyboardPresentable: PanModalPresentable {

var keyboardIsShown: Bool { get }

var minimumHeight: CGFloat { get }
var keyboardHeight: CGFloat { get }
var extrasHeight: CGFloat { get }
var contentWithKeyboardHeight: CGFloat { get }

var keyboardScrollView: UIScrollView? { get }
}
Loading